Java 如何通用化查询逻辑应对复杂的查询需求?

讨论 未结 8 44
jimisun
jimisun 会员 2022年4月17日 08:17 发表
<p>数据库有一些数据,如下模拟;</p> <pre><code class="language-java"> ArrayList&lt;User&gt; objects = Lists.newArrayList(); objects.add(new User("zhangsan", "123456", 18, 1)); objects.add(new User("lisi", "123456", 22, 1)); objects.add(new User("wangwu", "123456", 30, 1)); objects.add(new User("zhaoliu", "123456", 43, 1)); objects.add(new User("xiaoli", "xiaoli67889", 16, 0)); objects.add(new User("xiaona", "nai324389", 22, 0)); </code></pre> <h3>问题抛出</h3> <p>针对这些数据的查询而言,通常会在 service 层定义许多查询接口,例如</p> <ul> <li>查询性别为男的用户</li> <li>查询性别为男年龄 20 以下的用户</li> <li>查询性别为男年龄 20 以下的并且默认密码是 123456 的用户</li> <li>随需求增加...</li> </ul> <p>面对需求的变化多样,总是需要增量添加 controller 方法,service 方法,甚至 dao 方法,如何解决这个问题呢?</p> <h3>面向函数编程是否能满足呢?</h3> <pre><code class="language-java">//dao public static List&lt;User&gt; getUserList() { ArrayList&lt;User&gt; objects = Lists.newArrayList(); objects.add(new User("zhangsan", "123456", 18, 1)); objects.add(new User("lisi", "123456", 22, 1)); objects.add(new User("wangwu", "123456", 30, 1)); objects.add(new User("zhaoliu", "123456", 43, 1)); objects.add(new User("xiaoli", "xiaoli67889", 16, 0)); objects.add(new User("xiaona", "nai324389", 22, 0)); return objects; } </code></pre> <pre><code class="language-java">//service public static Optional getUserListByPredicate(Predicate&lt;User&gt; predicate) { List&lt;User&gt; userList = UserDao.getUserList(); ArrayList&lt;Object&gt; resultList = Lists.newArrayList(); for (User user : userList) { if (predicate.test(user)) { resultList.add(user); } } return Optional.ofNullable(resultList); } </code></pre> <pre><code class="language-java">//controller public static void main(String[] args) { //查询性别为男,年龄 20 以下,并且密码为默认密码 123456 的用户 Optional&lt;List&gt; result = UserService.getUserListByPredicate((User user) -&gt; { return user.getSex() == 1 &amp;&amp; user.getAge() &lt; 20 &amp;&amp; user.getPassword().equals("123456"); }); result.get().stream().forEach(user -&gt; System.out.println(user)); } </code></pre> <p>我的想法是,dao 层总是返回全量的数据(此处有问题性能问题),在 service 层对查询条件进行抽象,controller 只需要将查询条件传入即可。</p> <h3>更进一步用 stream 处理</h3> <pre><code class="language-java">//dao public static List&lt;User&gt; getUserList() { ArrayList&lt;User&gt; objects = Lists.newArrayList(); objects.add(new User("zhangsan", "123456", 18, 1)); objects.add(new User("lisi", "123456", 22, 1)); objects.add(new User("wangwu", "123456", 30, 1)); objects.add(new User("zhaoliu", "123456", 43, 1)); objects.add(new User("xiaoli", "xiaoli67889", 16, 0)); objects.add(new User("xiaona", "nai324389", 22, 0)); return objects; } </code></pre> <pre><code class="language-java">//controller 层 /** * 查询性别为男,年龄 20 以下,并且密码为默认密码 123456 的用户 * * @param args */ public static void main(String[] args) { List&lt;User&gt; userList = UserDao.getUserList(); userList.stream().filter( user -&gt; user.getSex() == 1 &amp;&amp; user.getAge() &lt; 20 &amp;&amp; user.getPassword().equals("123456") ).forEach(user -&gt; System.out.println(user)); } </code></pre> <p>我的想法是,controller 总是获取所有的数据,针对流根据业务进行业务操作。</p> <p>——————————</p> <p>以上两种方法是否可行? 问题?</p>
收藏(0)  分享
相关标签: 灌水交流
注意:本文归作者所有,未经作者允许,不得转载
8个回复
  • PerFectTime
    2022年4月17日 08:17
    我们是维护了一个数据列表的列视图权限,在此基础上通过列视图的数据类型(bit/string/字典)由可配置的高级查询功能可以对每一列的情况进行筛选
    0 0
  • eggoxygen
    2022年4月17日 08:30
    根据 ORM 框架不同有不同解决方案吧。 比如 JPA 的 Specification / QueryDsl 。 定义好需要查询的 Condition / Criteria 。 查询时传入即可。
    0 0
  • Leviathann
    2022年4月17日 08:30
    为什么不根据查询条件动态生成 sql
    0 0
  • micean
    2022年4月17日 10:18
    比如某个男人的 apijson……
    0 0
  • lower
    2022年4月17日 10:18
    直接让前端传 sql 语句吧,他们爱查啥查啥……
    0 0
  • EscYezi
    2022年4月17日 11:17
    看场景都是同一些数据同一些字段数值不同。controller 层只需要一个接口,定义一个含有多个字段的 vo ,本次查询用不到的字段和前端协商一个默认值就 ok dao 层 mybatis 的 xml 文件中 if 和 choose 根据各种情况拼接查询条件; mybatis-plus 也可以在拼接查询条件时增加 bool 参数指定是否拼接 全部查询出来数据少还好,多起来一次拿几十万数据出来,数据库和 java 服务压力都很大
    0 0
  • letitbesqzr
    2022年4月17日 14:17
    试试用 Aviator 之类的表达式解析工具? 让前端传表达式
    0 0