最近使用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. springcloud注解解释

    @SpringBootApplication是springboot启动类,包括三个注解,他们的作用分别是:  @Configuration:表示将该类作用springboot配置文件类  @Enabl ...

  2. 【使用篇二】SpringBoot文件上传(5)

    一.单个文件上传 1. 在static目录下创建upload.html <!DOCTYPE html> <html> <head> <meta charset ...

  3. 微信小程序 - 事件 | 传递 | 冒泡

    事件 常见的事件有: 类型 触发条件 最低版本 touchstart 手指触摸动作开始   touchmove 手指触摸后移动   touchcancel 手指触摸动作被打断,如来电提醒,弹窗   t ...

  4. CBV和FBV用户认证装饰器

    FBV装饰器用户验证 CBV装饰器用户验证 装饰器位置 或 或

  5. DLinNLP

    2015蒙特利尔深度学习暑期学校之自然语言处理篇 用户1737318 8月3日至8月12日在蒙特利尔举办的深度学习署期学校中,来自不同领域的深度学习顶尖学者 (Yoshua Bengio, Leon ...

  6. oracle左连接与右连接

    left join(左联接)       ---返回左表中的所有记录和右表中条件字段相等的记录. right join(右联接)     ---返回右表中的所有记录和左表中联结字段相等的记录 inne ...

  7. 项目:git+gitlab+jenkins+ansible上线网站

    项目需求 1. 在gitlab中创建一个项目 nginxinstall2. 编写playbook,实现一键部署nginx.部署一个静态测试页.测试部署结果要求: 部署nginx 端口:83 运行身份: ...

  8. [LeetCode] 5. Longest Palindromic Substring 最长回文子串

    Given a string s, find the longest palindromic substring in s. You may assume that the maximum lengt ...

  9. guava(二) Equivalence & Supplier

    一.Equivalence 一种判定两个实例是否相等的策略 全路径: com.google.common.base 声明: @GwtCompatible public abstract class E ...

  10. 企业应用向ASP.NET Core迁移

    有人说.NET在国内的氛围越来越不行了,看博客园文章的浏览量也起不来.是不是要转Java呢? 没有必要扯起语言的纷争,Java也好C#都只是语言是工具,各有各的使用场景.以前是C#非开源以及不能在Li ...