封装JpaSpecificationExecutor简化多条件查询

悠悠 2021-10-18 07:56 1021阅读 0赞

一、JpaSpecificationExecutor原生查询及其概述

1.1 概述

Spring Data JPA为我们提供了一系列的接口比如:Repository、CrudRepository、PagingAndSortingRepository、JpaRepository、JPASpecificationExecutor等。我们只需要继承这些接口就可以很方便的对数据库进行操作。但是当我们运用JPASpecificationExecutor接口进行一些比较复杂的条件查询的时候,就会显得有点麻烦,下面先来个查询的demo体验一下:

1.2 原生条件查询

  1. 我们假设usersRepositorySpecification已经继承了相关接口,以nameage为条件进行查询:
  2. /**
  3. * JpaSpecificationExecutor 多条件测试
  4. */
  5. @Test
  6. public void testJpaSpecificationExecutor2() {
  7. /**
  8. * Specification<Users>:用于封装查询条件
  9. */
  10. Specification<Users> spec = new Specification<Users>() {
  11. //Predicate:封装了 单个的查询条件
  12. /**
  13. * Root<Users> root:查询对象的属性的封装。
  14. * CriteriaQuery<?> query:封装了我们要执行的查询中的各个部分的信息,select from order by
  15. * CriteriaBuilder cb:查询条件的构造器。定义不同的查询条件
  16. */
  17. @Override
  18. public Predicate toPredicate(Root<Users> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
  19. List<Predicate> list = new ArrayList<>();
  20. list.add(cb.equal(root.get("name"),"张三三"));
  21. list.add(cb.equal(root.get("age"),20));
  22. Predicate[] arr = new Predicate[list.size()];
  23. return cb.and(list.toArray(arr));
  24. }
  25. };
  26. List<Users> list = this.usersRepositorySpecification.findAll(spec);
  27. for (Users users : list) {
  28. System.out.println(users);
  29. }
  30. }

二、对上述查询进行封装简化

  1. QueryWraper类,包装用于构建JPA动态查询时所需的对象

    1. public class QueryWraper<T> {
    2. public QueryWraper(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb, List<Predicate> predicates) {
    3. this.root = root;
    4. this.query = query;
    5. this.cb = cb;
    6. this.predicates = predicates;
    7. }
    8. /**
    9. * JPA Root
    10. */
    11. private Root<T> root;
    12. /**
    13. * JPA CriteriaBuilder
    14. */
    15. private CriteriaBuilder cb;
    16. /**
    17. * JPA Predicate 集合
    18. */
    19. private List<Predicate> predicates;
    20. /**
    21. * JPA 查询对象
    22. */
    23. private CriteriaQuery<?> query;
    24. /**
    25. * <pre>
    26. * 增加查询条件
    27. * <pre>
    28. * @param predicate
    29. * @author jojo 2014-8-12 下午3:12:36
    30. */
    31. public void addPredicate(Predicate predicate) {
    32. this.predicates.add(predicate);
    33. }
    34. public Root<T> getRoot() {
    35. return root;
    36. }
    37. public void setRoot(Root<T> root) {
    38. this.root = root;
    39. }
    40. public CriteriaBuilder getCb() {
    41. return cb;
    42. }
    43. public void setCb(CriteriaBuilder cb) {
    44. this.cb = cb;
    45. }
    46. public List<Predicate> getPredicates() {
    47. return predicates;
    48. }
    49. public void setPredicates(List<Predicate> predicates) {
    50. this.predicates = predicates;
    51. }
    52. public CriteriaQuery<?> getQuery() {
    53. return query;
    54. }
    55. public void setQuery(CriteriaQuery<?> query) {
    56. this.query = query;
    57. }
    58. }
  2. AbstractConditionBuilder抽象类,提供比如:in条件、between条件、like条件等一系列复杂查询条件

    1. public abstract class AbstractConditionBuilder<T> {
    2. /**
    3. * 添加in条件
    4. * @param queryWraper
    5. * @param column 哪个属性
    6. * @param values 在(in)哪些值里面
    7. */
    8. protected void addInConditionToColumn(QueryWraper<T> queryWraper, String column, Object values) {
    9. if (needAddCondition(values)) {
    10. Path<?> fieldPath = getPath(queryWraper.getRoot(), column); //得到最终的路径
    11. if(values.getClass().isArray()) {
    12. queryWraper.addPredicate(fieldPath.in((Object[])values)); //in :创建Predicate以测试表达式是否为参数列表的成员,返回Predicate
    13. }else if(values instanceof Collection) {
    14. queryWraper.addPredicate(fieldPath.in((Collection<?>)values));
    15. }
    16. }
    17. }
    18. /**
    19. * 添加between条件查询
    20. * @param queryWraper
    21. * @param experssion
    22. * @param minValue 范围下限
    23. * @param maxValue 范围上限
    24. */
    25. @SuppressWarnings({ "rawtypes", "unchecked" })
    26. protected void addBetweenConditionToColumn(QueryWraper<T> queryWraper, String column, Comparable minValue, Comparable maxValue) {
    27. if (minValue != null || maxValue != null) {
    28. Path<? extends Comparable> fieldPath = getPath(queryWraper.getRoot(), column);
    29. if(minValue != null && maxValue != null){
    30. queryWraper.addPredicate(queryWraper.getCb().between(fieldPath, minValue, processMaxValueOnDate(maxValue)));
    31. }else if(minValue != null){
    32. queryWraper.addPredicate(queryWraper.getCb().greaterThanOrEqualTo(fieldPath, minValue));
    33. }else if(maxValue != null){
    34. queryWraper.addPredicate(queryWraper.getCb().lessThanOrEqualTo(fieldPath, processMaxValueOnDate(maxValue)));
    35. }
    36. }
    37. }
    38. /**
    39. * 当范围查询的条件是小于,并且值的类型是Date时,将传入的Date值变为当天的夜里12点的值。
    40. * @param maxValue
    41. * @return
    42. * @author zhailiang
    43. * @since 2016年12月14日
    44. */
    45. @SuppressWarnings("rawtypes")
    46. private Comparable processMaxValueOnDate(Comparable maxValue) {
    47. if(maxValue instanceof Date) {
    48. maxValue = new DateTime(maxValue).withTimeAtStartOfDay().plusDays(1).plusSeconds(-1).toDate();
    49. }
    50. return maxValue;
    51. }
    52. /**
    53. * 添加大于条件查询
    54. * @param queryWraper
    55. * @param experssion
    56. * @param minValue
    57. */
    58. @SuppressWarnings({ "rawtypes", "unchecked" })
    59. protected void addGreaterThanConditionToColumn(QueryWraper<T> queryWraper, String column, Comparable minValue) {
    60. if (minValue != null) {
    61. Path<? extends Comparable> fieldPath = getPath(queryWraper.getRoot(), column);
    62. queryWraper.addPredicate(queryWraper.getCb().greaterThan(fieldPath, minValue));
    63. }
    64. }
    65. /**
    66. * 添加大于等于条件查询
    67. * @param queryWraper
    68. * @param experssion
    69. * @param minValue
    70. */
    71. @SuppressWarnings({ "rawtypes", "unchecked" })
    72. protected void addGreaterThanOrEqualConditionToColumn(QueryWraper<T> queryWraper, String column, Comparable minValue) {
    73. if (minValue != null) {
    74. Path<? extends Comparable> fieldPath = getPath(queryWraper.getRoot(), column);
    75. queryWraper.addPredicate(queryWraper.getCb().greaterThanOrEqualTo(fieldPath, minValue));
    76. }
    77. }
    78. /**
    79. * 添加小于条件查询
    80. * @param queryWraper
    81. * @param experssion
    82. * @param maxValue
    83. */
    84. @SuppressWarnings({ "unchecked", "rawtypes" })
    85. protected void addLessThanConditionToColumn(QueryWraper<T> queryWraper, String column, Comparable maxValue) {
    86. if (maxValue != null) {
    87. Path<? extends Comparable> fieldPath = getPath(queryWraper.getRoot(), column);
    88. queryWraper.addPredicate(queryWraper.getCb().lessThan(fieldPath, processMaxValueOnDate(maxValue)));
    89. }
    90. }
    91. /**
    92. * 添加小于等于条件查询
    93. * @param queryWraper
    94. * @param experssion
    95. * @param maxValue
    96. */
    97. @SuppressWarnings({ "unchecked", "rawtypes" })
    98. protected void addLessThanOrEqualConditionToColumn(QueryWraper<T> queryWraper, String column, Comparable maxValue) {
    99. if (maxValue != null) {
    100. Path<? extends Comparable> fieldPath = getPath(queryWraper.getRoot(), column);
    101. queryWraper.addPredicate(queryWraper.getCb().lessThanOrEqualTo(fieldPath, processMaxValueOnDate(maxValue)));
    102. }
    103. }
    104. /**
    105. * <pre>
    106. * 添加like条件
    107. * <pre>
    108. * @param queryWraper
    109. * @param column 指出要向哪个字段添加包含(like)条件
    110. * @param value like什么
    111. * @author jojo 2014-8-12 下午3:13:44
    112. */
    113. protected void addLikeConditionToColumn(QueryWraper<T> queryWraper, String column, String value) {
    114. if (StringUtils.isNotBlank(value)) {
    115. queryWraper.addPredicate(createLikeCondition(queryWraper, column, value));
    116. }
    117. }
    118. /**
    119. * @param queryWraper
    120. * @param column 查哪个字段
    121. * @param value 字段like什么
    122. * @return
    123. * @author zhailiang
    124. * @since 2016年12月13日
    125. */
    126. @SuppressWarnings("unchecked")
    127. protected Predicate createLikeCondition(QueryWraper<T> queryWraper, String column, String value) {
    128. Path<String> fieldPath = getPath(queryWraper.getRoot(), column);
    129. Predicate condition = queryWraper.getCb().like(fieldPath, "%" + value + "%");
    130. return condition;
    131. }
    132. /**
    133. * <pre>
    134. * 添加like条件
    135. * <pre>
    136. * @param queryWraper
    137. * @param column
    138. * @param value
    139. * @author jojo 2014-8-12 下午3:13:44
    140. */
    141. @SuppressWarnings("unchecked")
    142. protected void addStartsWidthConditionToColumn(QueryWraper<T> queryWraper, String column, String value) {
    143. if (StringUtils.isNotBlank(value)) {
    144. Path<String> fieldPath = getPath(queryWraper.getRoot(), column);
    145. queryWraper.addPredicate(queryWraper.getCb().like(fieldPath, value + "%"));
    146. }
    147. }
  1. /**
  2. * 添加等于条件
  3. * @param queryWraper
  4. * @param column 指出要向哪个字段添加条件
  5. * @param value 指定字段的值
  6. */
  7. protected void addEqualsConditionToColumn(QueryWraper<T> queryWraper, String column, Object value) {
  8. if(needAddCondition(value)) {
  9. Path<?> fieldPath = getPath(queryWraper.getRoot(), column);
  10. queryWraper.addPredicate(queryWraper.getCb().equal(fieldPath, value));
  11. }
  12. }
  13. /**
  14. * 添加不等于条件
  15. * @param queryWraper
  16. * @param column 指出要向哪个字段添加条件
  17. * @param value 指定字段的值
  18. */
  19. protected void addNotEqualsConditionToColumn(QueryWraper<T> queryWraper, String column, Object value) {
  20. if(needAddCondition(value)) {
  21. Path<?> fieldPath = getPath(queryWraper.getRoot(), column);
  22. queryWraper.addPredicate(queryWraper.getCb().notEqual(fieldPath, value));
  23. }
  24. }
  25. /**
  26. * <pre>
  27. *
  28. * <pre> 得到属性的路径
  29. * @param root
  30. * @param property
  31. * @return
  32. * @author jojo 2014-8-12 下午3:06:58
  33. */
  34. @SuppressWarnings("rawtypes")
  35. protected Path getPath(Root root, String property){
  36. //Path代表一个简单或者复杂的属性路径
  37. String[] names = StringUtils.split(property, "."); //比如路径是admin.role.resource,需要为resource创建path
  38. Path path = root.get(names[0]);
  39. for (int i = 1; i < names.length; i++) {
  40. path = path.get(names[i]); //创建与引用属性相对应的路径
  41. }
  42. return path;
  43. }
  44. /**
  45. * <pre>
  46. * 判断是否需要添加where条件
  47. * <pre>
  48. * @param value
  49. * @return
  50. * @author jojo 2014-8-12 下午3:07:00
  51. */
  52. @SuppressWarnings("rawtypes")
  53. protected boolean needAddCondition(Object value) {
  54. boolean addCondition = false;
  55. if (value != null) {
  56. if(value instanceof String) {
  57. if(StringUtils.isNotBlank(value.toString())) {
  58. addCondition = true;
  59. }
  60. }else if(value.getClass().isArray()) {
  61. if(ArrayUtils.isNotEmpty((Object[]) value)) {
  62. addCondition = true;
  63. }
  64. }else if(value instanceof Collection) {
  65. if(CollectionUtils.isNotEmpty((Collection) value)) {
  66. addCondition = true;
  67. }
  68. }else {
  69. addCondition = true;
  70. }
  71. }
  72. return addCondition;
  73. }
  74. }
  1. AbstractEventConditionBuilder抽象类,继承AbstractConditionBuilder类,根据传上来的条件对象,对AbstractConditionBuilder查询方法进行进一步封装。

    1. public abstract class AbstractEventConditionBuilder<T, C> extends AbstractConditionBuilder<T> {
    2. /**
    3. * 查询条件
    4. */
    5. private C condition;
    6. /**
    7. * @param condition 查询条件
    8. */
    9. public AbstractEventConditionBuilder(C condition){
    10. this.condition = condition;
    11. }
    12. /**
    13. * 向查询中添加包含(like)条件
    14. *
    15. * @param queryWraper
    16. * @param field 指出查询条件的值从condition对象的哪个字段里取,并且指出要向哪个字段添加包含(like)条件。(同一个字段名称)
    17. * @throws NoSuchMethodException
    18. * @throws InvocationTargetException
    19. * @throws IllegalAccessException
    20. */
    21. protected void addLikeCondition(QueryWraper<T> queryWraper, String field){
    22. addLikeCondition(queryWraper, field, field);
    23. }
    24. /**
    25. * 向查询中添加包含(like)条件
    26. *
    27. * @param queryWraper
    28. * @param field 指出查询条件的值从condition对象的哪个字段里取
    29. * @param column 指出要向哪个字段添加包含(like)条件
    30. * @throws NoSuchMethodException
    31. * @throws InvocationTargetException
    32. * @throws IllegalAccessException
    33. */
    34. protected void addLikeCondition(QueryWraper<T> queryWraper, String field, String column){
    35. addLikeConditionToColumn(queryWraper, column, (String)
    36. getValue(getCondition(), field)); //得到condition里面 field字段的值
    37. }
  1. /**
  2. * 向查询中添加包含(like)条件,%放在值后面
  3. *
  4. * @param queryWraper
  5. * @param field 指出查询条件的值从condition对象的哪个字段里取,并且指出要向哪个字段添加包含(like)条件。(同一个字段名称)
  6. * @throws NoSuchMethodException
  7. * @throws InvocationTargetException
  8. * @throws IllegalAccessException
  9. */
  10. protected void addStartsWidthCondition(QueryWraper<T> queryWraper, String field){
  11. addStartsWidthCondition(queryWraper, field, field);
  12. }
  13. /**
  14. * 向查询中添加包含(like)条件,%放在值后面
  15. *
  16. * @param queryWraper
  17. * @param field 指出查询条件的值从condition对象的哪个字段里取
  18. * @param column 指出要向哪个字段添加包含(like)条件
  19. * @throws NoSuchMethodException
  20. * @throws InvocationTargetException
  21. * @throws IllegalAccessException
  22. */
  23. protected void addStartsWidthCondition(QueryWraper<T> queryWraper, String field, String column){
  24. addStartsWidthConditionToColumn(queryWraper, column, (String)
  25. getValue(getCondition(), field));
  26. }
  27. /**
  28. * 向查询中添加等于(=)条件
  29. *
  30. * @param queryWraper
  31. * @param field 指出查询条件的值从condition对象的哪个字段里取,并且指出要向哪个字段添加条件。(同一个字段名称)
  32. * @throws NoSuchMethodException
  33. * @throws InvocationTargetException
  34. * @throws IllegalAccessException
  35. */
  36. protected void addEqualsCondition(QueryWraper<T> queryWraper, String field){
  37. addEqualsCondition(queryWraper, field, field);
  38. }
  39. /**
  40. * 向查询中添加等于(=)条件
  41. *
  42. * @param queryWraper
  43. * @param field 指出查询条件的值从condition对象的哪个字段里取
  44. * @param column 指出要向哪个字段添加条件
  45. * @throws NoSuchMethodException
  46. * @throws InvocationTargetException
  47. * @throws IllegalAccessException
  48. */
  49. protected void addEqualsCondition(QueryWraper<T> queryWraper, String field, String column){
  50. addEqualsConditionToColumn(queryWraper, column,
  51. getValue(getCondition(), field));
  52. }
  53. /**
  54. * 向查询中添加不等于(!=)条件
  55. *
  56. * @param queryWraper
  57. * @param field 指出查询条件的值从condition对象的哪个字段里取,并且指出要向哪个字段添加条件。(同一个字段名称)
  58. * @throws NoSuchMethodException
  59. * @throws InvocationTargetException
  60. * @throws IllegalAccessException
  61. */
  62. protected void addNotEqualsCondition(QueryWraper<T> queryWraper, String field){
  63. addNotEqualsCondition(queryWraper, field, field);
  64. }
  65. /**
  66. * 向查询中添加等于(=)条件
  67. *
  68. * @param queryWraper
  69. * @param field 指出查询条件的值从condition对象的哪个字段里取
  70. * @param column 指出要向哪个字段添加条件
  71. * @throws NoSuchMethodException
  72. * @throws InvocationTargetException
  73. * @throws IllegalAccessException
  74. */
  75. protected void addNotEqualsCondition(QueryWraper<T> queryWraper, String field, String column){
  76. addNotEqualsConditionToColumn(queryWraper, column, getValue(getCondition(), field));
  77. }
  78. /**
  79. * <pre>
  80. * 向查询中添加in条件
  81. * <pre>
  82. * @param queryWraper
  83. * @param field
  84. * @author jojo 2014-8-12 下午3:26:50
  85. */
  86. protected void addInCondition(QueryWraper<T> queryWraper, String field) {
  87. addInCondition(queryWraper, field, field);
  88. }
  89. /**
  90. * <pre>
  91. * 向查询中添加in条件
  92. * <pre>
  93. * @param queryWraper
  94. * @param field
  95. * @param column
  96. * @author jojo 2014-8-12 下午3:27:46
  97. */
  98. protected void addInCondition(QueryWraper<T> queryWraper, String field, String column) {
  99. addInConditionToColumn(queryWraper, column,
  100. getValue(getCondition(), field));
  101. }
  102. /**
  103. * <pre>
  104. * 向查询中添加between条件
  105. * <pre>
  106. * @param queryWraper
  107. * @param field
  108. * @author jojo 2014-8-12 下午3:26:50
  109. */
  110. protected void addBetweenCondition(QueryWraper<T> queryWraper, String field) {
  111. addBetweenCondition(queryWraper, field, field+"To", field);
  112. }
  113. /**
  114. * <pre>
  115. * 向查询中添加between条件
  116. * <pre>
  117. * @param queryWraper
  118. * @param field
  119. * @param column
  120. * @author jojo 2014-8-12 下午3:27:46
  121. */
  122. @SuppressWarnings("rawtypes")
  123. protected void addBetweenCondition(QueryWraper<T> queryWraper, String startField, String endField, String column) {
  124. addBetweenConditionToColumn(queryWraper, column,
  125. (Comparable)getValue(getCondition(), startField),
  126. (Comparable)getValue(getCondition(), endField));
  127. }
  128. /**
  129. * <pre>
  130. * 向查询中添加大于条件
  131. * <pre>
  132. * @param queryWraper
  133. * @param field
  134. * @author jojo 2014-8-12 下午3:26:50
  135. */
  136. protected void addGreaterThanCondition(QueryWraper<T> queryWraper, String field) {
  137. addGreaterThanCondition(queryWraper, field, field);
  138. }
  139. /**
  140. * <pre>
  141. * 向查询中添加大于条件
  142. * <pre>
  143. * @param queryWraper
  144. * @param field
  145. * @param column
  146. * @author jojo 2014-8-12 下午3:27:46
  147. */
  148. @SuppressWarnings("rawtypes")
  149. protected void addGreaterThanCondition(QueryWraper<T> queryWraper, String field, String column) {
  150. addGreaterThanConditionToColumn(queryWraper, column,
  151. (Comparable)getValue(getCondition(), field));
  152. }
  153. /**
  154. * <pre>
  155. * 向查询中添加大于等于条件
  156. * <pre>
  157. * @param queryWraper
  158. * @param field
  159. * @author jojo 2014-8-12 下午3:26:50
  160. */
  161. protected void addGreaterThanOrEqualCondition(QueryWraper<T> queryWraper, String field) {
  162. addGreaterThanOrEqualCondition(queryWraper, field, field);
  163. }
  164. /**
  165. * <pre>
  166. * 向查询中添加大于等于条件
  167. * <pre>
  168. * @param queryWraper
  169. * @param field
  170. * @param column
  171. * @author jojo 2014-8-12 下午3:27:46
  172. */
  173. @SuppressWarnings("rawtypes")
  174. protected void addGreaterThanOrEqualCondition(QueryWraper<T> queryWraper, String field, String column) {
  175. addGreaterThanOrEqualConditionToColumn(queryWraper, column,
  176. (Comparable)getValue(getCondition(), field));
  177. }
  178. /**
  179. * <pre>
  180. * 向查询中添加小于条件
  181. * <pre>
  182. * @param queryWraper
  183. * @param field
  184. * @author jojo 2014-8-12 下午3:26:50
  185. */
  186. protected void addLessThanCondition(QueryWraper<T> queryWraper, String field) {
  187. addLessThanCondition(queryWraper, field, field);
  188. }
  189. /**
  190. * <pre>
  191. * 向查询中添加小于条件
  192. * <pre>
  193. * @param queryWraper
  194. * @param field
  195. * @param column
  196. * @author jojo 2014-8-12 下午3:27:46
  197. */
  198. @SuppressWarnings("rawtypes")
  199. protected void addLessThanCondition(QueryWraper<T> queryWraper, String field, String column) {
  200. addLessThanConditionToColumn(queryWraper, column,
  201. (Comparable)getValue(getCondition(), field));
  202. }
  203. /**
  204. * <pre>
  205. * 向查询中添加小于等于条件
  206. * <pre>
  207. * @param queryWraper
  208. * @param field
  209. * @author jojo 2014-8-12 下午3:26:50
  210. */
  211. protected void addLessThanOrEqualCondition(QueryWraper<T> queryWraper, String field) {
  212. addLessThanOrEqualCondition(queryWraper, field, field);
  213. }
  214. /**
  215. * <pre>
  216. * 向查询中添加小于等于条件
  217. * <pre>
  218. * @param queryWraper
  219. * @param field
  220. * @param column
  221. * @author jojo 2014-8-12 下午3:27:46
  222. */
  223. @SuppressWarnings("rawtypes")
  224. protected void addLessThanOrEqualCondition(QueryWraper<T> queryWraper, String field, String column) {
  225. addLessThanOrEqualConditionToColumn(queryWraper, column,
  226. (Comparable)getValue(getCondition(), field));
  227. }
  228. /**
  229. *
  230. * @param condition 从这个对象里面查
  231. * @param field 要查询的属性
  232. * @return
  233. */
  234. private Object getValue(C condition, String field) {
  235. try {
  236. //得到condition对象中field属性的值
  237. //使用示例:getProperty(book,"authors[0].favorites(food)")
  238. return PropertyUtils.getProperty(condition, field);
  239. } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
  240. e.printStackTrace();
  241. }
  242. return null;
  243. }
  244. /**
  245. * @return the condition
  246. */
  247. public C getCondition() {
  248. return condition;
  249. }
  250. /**
  251. * @param condition the condition to set
  252. */
  253. public void setCondition(C condition) {
  254. this.condition = condition;
  255. }
  256. }
  1. MyImoocSpecification类,继承AbstractEventConditionBuilder类,并实现Specification接口,重写toPredicate()方法,使用时继承该类即可

    1. public abstract class MySpecification<T, C> extends AbstractEventConditionBuilder<T, C> implements Specification<T> {
    2. //AbstractEventConditionBuilder里面封装了添加各种查询条件的方法
    3. /**
    4. * @param condition
    5. */
    6. public MySpecification(C condition) {
    7. super(condition);
    8. }
    9. /**
    10. *
    11. * 构建查询条件,子类必须实现addCondition方法来编写查询的逻辑。
    12. *
    13. * 子类可以通过addFetch方法控制查询的关联和抓取行为。
    14. *
    15. */
    16. @Override
    17. public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
    18. if (Long.class != query.getResultType()) {
    19. addFetch(root);
    20. }
    21. List<Predicate> predicates = new ArrayList<Predicate>();
    22. QueryWraper<T> queryWraper = new QueryWraper<T>(root, query, cb, predicates);
    23. addCondition(queryWraper);
    24. Predicate permissionCondition = getPermissionCondition(queryWraper);
    25. if (permissionCondition != null) {
    26. queryWraper.addPredicate(permissionCondition);
    27. }
    28. return cb.and(predicates.toArray(new Predicate[predicates.size()]));
    29. }
    30. /**
    31. * 添加权限条件,如果要查询的domain实现了{@link ManagedByOrgan}接口,那么传入的Condition对象也应该实现
    32. * {@link ManagedByOrgan}接口,
    33. * 程序会尝试从Condition对象获取organFullId,然后作为like查询条件添加到查询中。
    34. * 查出所有以传入的organFullId开头的domain.
    35. *
    36. * @param queryWraper
    37. * @return
    38. */
    39. protected Predicate getPermissionCondition(QueryWraper<T> queryWraper) {
    40. return null;
    41. }
    42. /**
    43. * <pre>
    44. * 子类可以通过覆盖此方法实现关联抓取,避免n+1查询
    45. *
    46. * <pre>
    47. *
    48. * @param root
    49. * @author jojo 2014-7-22 上午9:49:26
    50. */
    51. protected void addFetch(Root<T> root) {
    52. }
    53. protected abstract void addCondition(QueryWraper<T> queryWraper); //钩子方法,子类实现 自动调用
    54. }

三、使用示例

3.1 创建条件封装对象

  1. public class AdminCondition {
  2. private String username;
  3. /**
  4. * @return the username
  5. */
  6. public String getUsername() {
  7. return username;
  8. }
  9. /**
  10. * @param username the username to set
  11. */
  12. public void setUsername(String username) {
  13. this.username = username;
  14. }
  15. }

3.2 继承MySpecification类

  1. 传入条件封装对象,以及结果实体类型
  2. public class AdminSpec extends ImoocSpecification<Admin, AdminCondition> {
  3. public AdminSpec(AdminCondition condition) {
  4. super(condition);
  5. }
  6. @Override
  7. protected void addCondition(QueryWraper<Admin> queryWraper) {
  8. addLikeCondition(queryWraper, "username");
  9. }
  10. }

3.3 调用

  1. public class AdminServiceImpl implements AdminService {
  2. @Autowired
  3. private AdminRepository adminRepository;
  4. public Page<AdminInfo> query(AdminCondition condition, Pageable pageable) {
  5. Page<Admin> admins = adminRepository.findAll(new AdminSpec(condition), pageable);
  6. return QueryResultConverter.convert(admins, AdminInfo.class, pageable);
  7. }
  8. }

发表评论

表情:
评论列表 (有 0 条评论,1021人围观)

还没有评论,来说两句吧...

相关阅读

    相关 条件查询

    > 多条件查询就是将sql语句进行拼接,在这里需要用到一个where 1=1 表示条件永远成立,这样就少了对where和and的处理 上代码,一目了然 String