最近使用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. 在 Oracle 中使用正则表达式

    Oracle使用正则表达式离不开这4个函数: 1.regexp_like 2.regexp_substr 3.regexp_instr 4.regexp_replace 看函数名称大概就能猜到有什么用 ...

  2. java执行hive命令或者脚本

    java执行脚本 import java.io.*; import java.text.DateFormat; import java.text.SimpleDateFormat; import ja ...

  3. java修饰符的总结

    引言:Java的修饰符根据修饰的对象不同,分为类修饰符.方法修饰符.变量修饰符,其中每种修饰符又分为访问控制修饰符和非访问控制修饰符.访问控制存在的原因:a.让客户端程序员无法触及他们不应该触及的部分 ...

  4. [BZOJ3538]坑爹的GPS

    题目描述 Description 有一天,\(FJ\) 买了一辆车,但是,他一手下载了两个\(GPS\) 系统.好了现在麻烦的事情来了,\(GPS\) 有一个功能大概大家也知道,如果\(FJ\) 没有 ...

  5. [LeetCode] 13. Roman to Integer 罗马数字转化成整数

    Roman numerals are represented by seven different symbols: I, V, X, L, C, D and M. Symbol Value I 1 ...

  6. [LeetCode] 39. Combination Sum 组合之和

    Given a set of candidate numbers (candidates) (without duplicates) and a target number (target), fin ...

  7. IDEA中阿里P3C插件的安装与使用

    在线安装: 离线安装: https://plugins.jetbrains.com/plugin/10046-alibaba-java-coding-guidelines/versions

  8. Windows搭建FTP/Http文件共享(利用IIS)

    控制面板——程序——添加功能 勾选Ftp服务器.万维网服务.IIS管理控制台 然后,计算机——右键管理——服务和应用程序,添加网站和添加Ftp IP设置为 未分配 或 本机获取到的静态IP即可. 然后 ...

  9. 微信企业号消息接口PHP SDK

    微信企业号消息接口PHP SDK及Demo <?php /* 方倍工作室 http://www.fangbei.org/ CopyRight 2015 All Rights Reserved * ...

  10. base62与long的相互转换

    public static class Converter { private static String keys = "0123456789abcdefghijklmnopqrstuvw ...