最近使用spring data jpa做了两个项目,对于动态查询的不友好做了个类似hibernate的封装,记录也分享下

首先定义一个所有条件的容器,继承Specification

  1. /**
  2. * 定义一个查询条件容器
  3. * @author lee
  4. *
  5. * @param <T>
  6. */
  7. public class Criteria<T> implements Specification<T>{
  8. private List<Criterion> criterions = new ArrayList<Criterion>();
  9. public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query,
  10. CriteriaBuilder builder) {
  11. if (!criterions.isEmpty()) {
  12. List<Predicate> predicates = new ArrayList<Predicate>();
  13. for(Criterion c : criterions){
  14. predicates.add(c.toPredicate(root, query,builder));
  15. }
  16. // 将所有条件用 and 联合起来
  17. if (predicates.size() > 0) {
  18. return builder.and(predicates.toArray(new Predicate[predicates.size()]));
  19. }
  20. }
  21. return builder.conjunction();
  22. }
  23. /**
  24. * 增加简单条件表达式
  25. * @Methods Name add
  26. * @Create In 2012-2-8 By lee
  27. * @param expression0 void
  28. */
  29. public void add(Criterion criterion){
  30. if(criterion!=null){
  31. criterions.add(criterion);
  32. }
  33. }
  34. }

然后是各种条件组装类,我首先做了一个接口来包装各种条件

  1. /**
  2. * 条件接口
  3. * 用户提供条件表达式接口
  4. * @Class Name Criterion
  5. * @Author lee
  6. * @Create In 2012-2-8
  7. */
  8. public interface Criterion {
  9. public enum Operator {
  10. EQ, NE, LIKE, GT, LT, GTE, LTE, AND, OR
  11. }
  12. public Predicate toPredicate(Root<?> root, CriteriaQuery<?> query,
  13. CriteriaBuilder builder);
  14. }

然后是针对不同类型条件处理的实现

一个是简单比较类型的处理

  1. /**
  2. * 简单条件表达式
  3. * @author lee
  4. *
  5. */
  6. public class SimpleExpression implements Criterion{
  7. private String fieldName;       //属性名
  8. private Object value;           //对应值
  9. private Operator operator;      //计算符
  10. protected SimpleExpression(String fieldName, Object value, Operator operator) {
  11. this.fieldName = fieldName;
  12. this.value = value;
  13. this.operator = operator;
  14. }
  15. public String getFieldName() {
  16. return fieldName;
  17. }
  18. public Object getValue() {
  19. return value;
  20. }
  21. public Operator getOperator() {
  22. return operator;
  23. }
  24. @SuppressWarnings({ "rawtypes", "unchecked" })
  25. public Predicate toPredicate(Root<?> root, CriteriaQuery<?> query,
  26. CriteriaBuilder builder) {
  27. Path expression = null;
  28. if(fieldName.contains(".")){
  29. String[] names = StringUtils.split(fieldName, ".");
  30. expression = root.get(names[0]);
  31. for (int i = 1; i < names.length; i++) {
  32. expression = expression.get(names[i]);
  33. }
  34. }else{
  35. expression = root.get(fieldName);
  36. }
  37. switch (operator) {
  38. case EQ:
  39. return builder.equal(expression, value);
  40. case NE:
  41. return builder.notEqual(expression, value);
  42. case LIKE:
  43. return builder.like((Expression<String>) expression, "%" + value + "%");
  44. case LT:
  45. return builder.lessThan(expression, (Comparable) value);
  46. case GT:
  47. return builder.greaterThan(expression, (Comparable) value);
  48. case LTE:
  49. return builder.lessThanOrEqualTo(expression, (Comparable) value);
  50. case GTE:
  51. return builder.greaterThanOrEqualTo(expression, (Comparable) value);
  52. default:
  53. return null;
  54. }
  55. }
  56. }

一个逻辑条件计算实现

  1. /**
  2. * 逻辑条件表达式 用于复杂条件时使用,如但属性多对应值的OR查询等
  3. * @author lee
  4. *
  5. */
  6. public class LogicalExpression implements Criterion {
  7. private Criterion[] criterion;  // 逻辑表达式中包含的表达式
  8. private Operator operator;      //计算符
  9. public LogicalExpression(Criterion[] criterions, Operator operator) {
  10. this.criterion = criterions;
  11. this.operator = operator;
  12. }
  13. public Predicate toPredicate(Root<?> root, CriteriaQuery<?> query,
  14. CriteriaBuilder builder) {
  15. List<Predicate> predicates = new ArrayList<Predicate>();
  16. for(int i=0;i<this.criterion.length;i++){
  17. predicates.add(this.criterion[i].toPredicate(root, query, builder));
  18. }
  19. switch (operator) {
  20. case OR:
  21. return builder.or(predicates.toArray(new Predicate[predicates.size()]));
  22. default:
  23. return null;
  24. }
  25. }
  26. }

添加一个组装工厂类

  1. /**
  2. * 条件构造器
  3. * 用于创建条件表达式
  4. * @Class Name Restrictions
  5. * @Author lee
  6. */
  7. public class Restrictions {
  8. /**
  9. * 等于
  10. * @param fieldName
  11. * @param value
  12. * @param ignoreNull
  13. * @return
  14. */
  15. public static SimpleExpression eq(String fieldName, Object value, boolean ignoreNull) {
  16. if(StringUtils.isEmpty(value))return null;
  17. return new SimpleExpression (fieldName, value, Operator.EQ);
  18. }
  19. /**
  20. * 不等于
  21. * @param fieldName
  22. * @param value
  23. * @param ignoreNull
  24. * @return
  25. */
  26. public static SimpleExpression ne(String fieldName, Object value, boolean ignoreNull) {
  27. if(StringUtils.isEmpty(value))return null;
  28. return new SimpleExpression (fieldName, value, Operator.NE);
  29. }
  30. /**
  31. * 模糊匹配
  32. * @param fieldName
  33. * @param value
  34. * @param ignoreNull
  35. * @return
  36. */
  37. public static SimpleExpression like(String fieldName, String value, boolean ignoreNull) {
  38. if(StringUtils.isEmpty(value))return null;
  39. return new SimpleExpression (fieldName, value, Operator.LIKE);
  40. }
  41. /**
  42. *
  43. * @param fieldName
  44. * @param value
  45. * @param matchMode
  46. * @param ignoreNull
  47. * @return
  48. */
  49. public static SimpleExpression like(String fieldName, String value,
  50. MatchMode matchMode, boolean ignoreNull) {
  51. if(StringUtils.isEmpty(value))return null;
  52. return null;
  53. }
  54. /**
  55. * 大于
  56. * @param fieldName
  57. * @param value
  58. * @param ignoreNull
  59. * @return
  60. */
  61. public static SimpleExpression gt(String fieldName, Object value, boolean ignoreNull) {
  62. if(StringUtils.isEmpty(value))return null;
  63. return new SimpleExpression (fieldName, value, Operator.GT);
  64. }
  65. /**
  66. * 小于
  67. * @param fieldName
  68. * @param value
  69. * @param ignoreNull
  70. * @return
  71. */
  72. public static SimpleExpression lt(String fieldName, Object value, boolean ignoreNull) {
  73. if(StringUtils.isEmpty(value))return null;
  74. return new SimpleExpression (fieldName, value, Operator.LT);
  75. }
  76. /**
  77. * 大于等于
  78. * @param fieldName
  79. * @param value
  80. * @param ignoreNull
  81. * @return
  82. */
  83. public static SimpleExpression lte(String fieldName, Object value, boolean ignoreNull) {
  84. if(StringUtils.isEmpty(value))return null;
  85. return new SimpleExpression (fieldName, value, Operator.GTE);
  86. }
  87. /**
  88. * 小于等于
  89. * @param fieldName
  90. * @param value
  91. * @param ignoreNull
  92. * @return
  93. */
  94. public static SimpleExpression gte(String fieldName, Object value, boolean ignoreNull) {
  95. if(StringUtils.isEmpty(value))return null;
  96. return new SimpleExpression (fieldName, value, Operator.LTE);
  97. }
  98. /**
  99. * 并且
  100. * @param criterions
  101. * @return
  102. */
  103. public static LogicalExpression and(Criterion... criterions){
  104. return new LogicalExpression(criterions, Operator.AND);
  105. }
  106. /**
  107. * 或者
  108. * @param criterions
  109. * @return
  110. */
  111. public static LogicalExpression or(Criterion... criterions){
  112. return new LogicalExpression(criterions, Operator.OR);
  113. }
  114. /**
  115. * 包含于
  116. * @param fieldName
  117. * @param value
  118. * @return
  119. */
  120. @SuppressWarnings("rawtypes")
  121. public static LogicalExpression in(String fieldName, Collection value, boolean ignoreNull) {
  122. if(ignoreNull&&(value==null||value.isEmpty())){
  123. return null;
  124. }
  125. SimpleExpression[] ses = new SimpleExpression[value.size()];
  126. int i=0;
  127. for(Object obj : value){
  128. ses[i]=new SimpleExpression(fieldName,obj,Operator.EQ);
  129. i++;
  130. }
  131. return new LogicalExpression(ses,Operator.OR);
  132. }
  133. }

使用方法如下

  1. Criteria<Event> c = new Criteria<Event>();
  2. c.add(Restrictions.like("code", searchParam.getCode(), true));
  3. c.add(Restrictions.eq("level", searchParam.getLevel(), false));
  4. c.add(Restrictions.eq("mainStatus", searchParam.getMainStatus(), true));
  5. c.add(Restrictions.eq("flowStatus", searchParam.getFlowStatus(), true));
  6. c.add(Restrictions.eq("createUser.userName", searchParam.getCreateUser(), true));
  7. c.add(Restrictions.lte("submitTime", searchParam.getStartSubmitTime(), true));
  8. c.add(Restrictions.gte("submitTime", searchParam.getEndSubmitTime(), true));
  9. c.add(Restrictions.eq("needFollow", searchParam.getIsfollow(), true));
  10. c.add(Restrictions.ne("flowStatus", CaseConstants.CASE_STATUS_DRAFT, true));
  11. c.add(Restrictions.in("solveTeam.code",teamCodes, true));
  12. eventDao.findAll(c);

其中eventDao为继承JpaSpecificationExecutor的接口类

 原文:http://lee1177.iteye.com/blog/1994295

SPring boot jpa 封装查询条件的更多相关文章

  1. Spring Boot JPA的查询语句

    文章目录 准备工作 Containing, Contains, IsContaining 和 Like StartsWith EndsWith 大小写不敏感 Not @Query Spring Boo ...

  2. spring boot jpa 复杂查询 动态查询 连接and和or 模糊查询 分页查询

    最近项目中用到了jpa,刚接触的时候有些激动,以前的到层忽然不用写sql不用去自己实现了,只是取个方法名就实现了,太惊艳了,惊为天人,但是慢慢的就发现不是这么回事了,在动态查询的时候,不知道怎么操作了 ...

  3. 【Spring Data 系列学习】Spring Data JPA 自定义查询,分页,排序,条件查询

    Spring Boot Jpa 默认提供 CURD 的方法等方法,在日常中往往时无法满足我们业务的要求,本章节通过自定义简单查询案例进行讲解. 快速上手 项目中的pom.xml.application ...

  4. Spring Boot 入门系列(二十七)使用Spring Data JPA 自定义查询如此简单,完全不需要写SQL!

    前面讲了Spring Boot 整合Spring Boot JPA,实现JPA 的增.删.改.查的功能.JPA使用非常简单,只需继承JpaRepository ,无需任何数据访问层和sql语句即可实现 ...

  5. Spring NamedParameterJdbcTemplate命名参数查询条件封装, NamedParameterJdbcTemplate查询封装

    Spring NamedParameterJdbcTemplate命名参数查询条件封装, NamedParameterJdbcTemplate查询封装 >>>>>> ...

  6. 序列化表单为json对象,datagrid带额外参提交一次查询 后台用Spring data JPA 实现带条件的分页查询 多表关联查询

    查询窗口中可以设置很多查询条件 表单中输入的内容转为datagrid的load方法所需的查询条件向原请求地址再次提出新的查询,将结果显示在datagrid中 转换方法看代码注释 <td cols ...

  7. Spring Boot(五):Spring Boot Jpa 的使用

    在上篇文章Spring Boot(二):Web 综合开发中简单介绍了一下 Spring Boot Jpa 的基础性使用,这篇文章将更加全面的介绍 Spring Boot Jpa 常见用法以及注意事项. ...

  8. Spring Boot Jpa 的使用

    Spring Boot Jpa 介绍 首先了解 Jpa 是什么? Jpa (Java Persistence API) 是 Sun 官方提出的 Java 持久化规范.它为 Java 开发人员提供了一种 ...

  9. (转)Spring Boot(五):Spring Boot Jpa 的使用

    http://www.ityouknow.com/springboot/2016/08/20/spring-boot-jpa.html 在上篇文章Spring Boot(二):Web 综合开发中简单介 ...

随机推荐

  1. Win10打开控制面板的方式

    Win10打开控制面板的方式方式1:1.打开运行框    windows键 + R2.在运行框中输入 control 方式2:右击开始图标->控制面板 方式3:在命令行cmd中输入 contro ...

  2. (translation.E004) You have provided a value for the LANGUAGE_CODE setting that is not in the LANGUAGES setting.

    django3.0开始LANGUAGE_CODE前面必须配相应的LANGUAGES配置如下: from django.utils.translation import gettext_lazy as ...

  3. ETA:

    Route-based models - Simple Additive Model- Data-driven Model Path-free models - MURAT Model Chun-Hs ...

  4. LeetCode 154. Find Minimum in Rotated Sorted Array II寻找旋转排序数组中的最小值 II (C++)

    题目: Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand. ( ...

  5. generator(生成器)

    什么是generator函数: 在js中,一个函数一旦执行,就会运行到最后或者遇到return时结束,运行期间不会有其它代码能打断它,也不能从外部再传入值到函数体内. generator函数的出现就可 ...

  6. xpath获取标签对本身含内容, 获取html内容

    通常使用xpath我们直接定位到标签后, 使用/text() 或 //text()来获取标签对之间的文本值, 但特殊情况下我们也需要获取标签本身含文本值, 操作如下: 文件为html, 标签对结构如下 ...

  7. java8 关于Set集合的线程安全使用

    场景:并发多线程,往Set集合中存放数据时,发现最终的数量结果不对,经过排查,没有使用线程安全的Set导致 哈哈,不会描述,代码解释一切,下面代码,使用的 Sets.newHashSet() 和 Co ...

  8. SpringBoot-dubbo自定义负载均衡实现简单灰度

    本文介绍如何利用dubbo自定义负载实现简单灰度(用户纬度,部分用户访问一个服务,其余访问剩余服务). 其实在这之前,对dubbo了解的也不是很多,只是简单的使用过,跑了几个demo而已,但是得知接下 ...

  9. 如何同时在Isilon的所有网卡上抓取网络包?

    命令行如下: cd /ifs/data/Isilon_Support/ mkdir $(date +%m%d%Y) isi_for_array 'for i in `ifconfig | grep - ...

  10. SQL Inserted 触发器游标结合实例

    SqlServer的Inserted可能是一个集合而不是一条数据,如果有如果需要对插入数据进行处理,有时需要用游标逐条处理 FROM inserted) --插入和更新 declare cur cur ...