最近使用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. Socket-window通讯

    #define _WINSOCK_DEPRECATED_NO_WARNINGS #include<WINSOCK2.H> #include<STDIO.H> #include& ...

  2. Dubbo介绍(一)

    Dubbo是一个分布式.高性能.透明化的 RPC 服务框架,作用是提供服务自动注册.自动发现等高效服务治理方案. 一.Dubbo架构图 Provider:提供者,服务发布方 Consumer:消费者, ...

  3. 八种排序算法原理及Java实现

    原文链接:http://ju.outofmemory.cn/entry/372908

  4. vscode使用插件来添加文件说明和函数说明——42header——psioniq File Header——koroFileHeader

    安装号以后,设置快捷键如下: 同时需要根据自己的需要的修改json文件 // 文件头部注释 "fileheader.customMade": { "Description ...

  5. 洛谷 U87561 魔法月饼

    洛谷 U87561 魔法月饼 洛谷传送门 题目背景 \(9102\)年的中秋节注定与往年不同...因为在\(9102\)年的中秋节前夕,\(Seaway\)被告知今年的中秋节要新出一款月饼--魔法月饼 ...

  6. JDOJ 3055: Nearest Common Ancestors

    JDOJ 3055: Nearest Common Ancestors JDOJ传送门 Description 给定N个节点的一棵树,有K次查询,每次查询a和b的最近公共祖先. 样例中的16和7的公共 ...

  7. 四则运算web版需求规格说明书

    目录 1引言... 4 1.1  目的... 4 1.2  背景... 4 1.3  术语... 4 1.4  预期读者与阅读建议... 5 1.5  参考资料... 6 1.6  需求描述约定... ...

  8. C++面向对象程序设计学习笔记(4)

    类与对象(2) string类 C++不仅向下兼容C的字符表示方法,也声明了一种更方便的字符串类型,即string类. 想要使用string类,必须包括头文件string,即要声明 #include& ...

  9. [Python] Python 模拟登录,并请求

    Python 模拟登录,并请求 # encoding: utf- import requests import socket import time socket.setdefaulttimeout( ...

  10. [ Python入门教程 ] Python的控制语句

    Python控制语句由条件语句.循环语句构成.控制语句根据条件表达式控制程序的流转.本章将介绍Python中控制语句的基本语法. 条件判断语句 (1)if条件语句 if语句用于检测某个条件是否成立.如 ...