最近开始使用Spring开发新项目了,开发新项目必定少不了折腾增删查改。 其中模糊查询,精确查询,分页查询也算是不好对付的功能,需要手写大量重复的代码来实现相关的功能,如何优雅的实现查询功能呢?
首先上两张截图。
第一张截图是分页列出活动,可以根据活动名称和活动内容进行模糊查询。 举办机构,举办年份,活动分类为可选项。如指定了年份就会检索相应年份的数据。
第二张截图是列出分类。 可以根据分类名称进行模糊查询。
可以发现,两个listData 方法均只有4行代码。
第一行指定模糊查询的列名s,第二行获取一个 Specification 对象,并且传递需精确匹配的参数。 第三行查询。第四行return 。
以下是获取Specification对象的实现 。 这里使用了静态泛型方法,关键在于熟练的使用 CriteriaBuilder 来构建or and like eq 等操作符号。
最终的实现效果如下:
这里需要根据fid 隔离不同用户的数据,所以每条sql查询都带有一个fid=? 条件查询,当然这个条件是通过 addCommon 方法来实现的。 如果有其他共同的查询条件,在此方法中实现即可。
PageRequestUtil 类的实现,简单的实现了参数的校验。 比如页码不能为负数,每页最多100条数据。 如果 numPerPage大于100,很有可能就是有人在采集你网站的数据了,虽然这种限制也根本阻止不了别人的采集行为。但至少可以使得程序更加安全一点,不会一次性查询大量数据导致mysql崩溃。
如何应对新的业务, 如果只有根据某些字段进行模糊查询, 只需写4行代码足以实现分页功能。
如何应对业务的变更, 今天产品说根据活动名称检索足以,但第二天又说需要跟据活动内容进行检索,或者新增检索字段。 那么还是只需要修改第一行代码即可。
以下是更新内容:
2019-04-26
本博文适用场景。单表查询 where A.a = ? and A.b = ? and (A.c like ? or A.d like ?) , 参数不定, param1 为空的话 where 条件退化为 A.b =param2 and (A.c like ? or A.d like ?) , param2 为空的话 where 条件退化 A.a = param1 and (A.c like ? or A.d like ?) , searchword 为空的话, where 条件退化为 A.a = param1 and A.b = param2 。
关于 where 条件的排序问题, 我坚信精确匹配放在迷糊查询前, 整型匹配放在字符串匹配前 ,有索引的列放在没有索引的列前,这样可以提高查询速度。
A.a = 100 and A.b = 'lizhifeng' and A.c like '%李%' > A.b = 'lizhifeng' and A.a = 100 and A.c like '%李%' > A.c like '%李%' and A.b = 'lizhifeng' and A.a = 100 . 当然我也更愿意相信现在的sql查询器强大得到能够自动优化查询条件。
夸表查询,我还没有找到很好的解决办法,不过我觉得使用 @Query 和 hql 还是不错的选择。
2019-04-28
今天下午在尝试构建一个 SpecificationBuilder 工具 ,看似使用起来还是非常简单的,但是实现十分丑陋,就不敢拿出来丢人了。
2019-04-29
虽然实现得非常垃圾,但毕竟是亲手实现的,所以SpecificationBuilder 的代码还是贴出来。
https://github.com/lzflzf/SpecificationBuilder/blob/master/src/main/SpecificationBuilder.java
看同事一直在使用 ExampleMatcher 。