最近使用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. 生产者和消费者模型producer and consumer(单线程下实现高并发)

    #1.生产者和消费者模型producer and consumer modelimport timedef producer(): ret = [] for i in range(2): time.s ...

  2. ESP8266 LUA脚本语言开发: 准备工作-LUA开发说明

    前言 开发Lua需要使用这个软件 注:该软件需要按照JDK  即 JAVA虚拟机,如果没有安装过JDK,请先看JDK安装教程安装JDK USB线连接开发板接入电脑 选择自己的串口号 波特率115200 ...

  3. 6.Go-错误,defer,panic和recover

    6.1.错误 Go语言中使用builtin包下error接口作为错误类型 Go语言中错误都作为方法/函数的返回值 自定义错误类型 //Learn_Go/main.go package main imp ...

  4. CSP2019题解

    CSP2019题解 格雷码 按照生成的规则模拟一下即可. 代码 括号树 看到括号匹配首先想到用栈,然后又在树上就可以想到可追溯化栈. 令\(a_i=1\)表示\(i\)号节点上的括号为(,否则为), ...

  5. [NOI2014]动物园(KMP,字符串)

    半年前看这题还感觉很神仙,做不动(没看题解). 现在过来看发现……这tm就是一个sb题…… 首先题面已经提示我们用 KMP 了.那 KMP 究竟能干啥呢? 看 $num$ 的定义.发现对于前缀 $i$ ...

  6. linux shell根据端口返回进程号杀死进程的方法

    linux shell根据端口返回进程号杀死进程的方法<pre>kill `lsof -t -i:9501`</pre>这个就是杀死9501端口的进程号

  7. Mysql插入text类型字段错误记录 com.mysql.jdbc.MysqlDataTruncation: Data truncation: #22001

    一次插入操作报如下错误 com.mysql.jdbc.MysqlDataTruncation: Data truncation: #22001 是说字段值长度超过限制. MySQL TEXT数据类型的 ...

  8. 常见的Redis面试"刁难"问题,值得一读

    Redis有哪些数据结构? 字符串String.字典Hash.列表List.集合Set.有序集合SortedSet. 如果你是Redis中高级用户,还需要加上下面几种数据结构HyperLogLog.G ...

  9. 【01】Saltstack:从零开始 Saltstack

    写在前面的话 最近一直都在整理以前的乱七八糟的笔记,所以会有很多老旧的东西都会被拉出来重新遛遛.算是再度系统的进行学习. 关于 Saltstack 的一些概念 Saltstack 是基于 Python ...

  10. 深入V8引擎-编译启动

    记录一下步骤,方便以后换了电脑重新编译. 1.搞定depot_tools,git地址:git clone https://chromium.googlesource.com/chromium/tool ...