1、定義條件容器
package cn.aid.common.utils.jpa.condition; import org.springframework.data.jpa.domain.Specification; import javax.persistence.criteria.*; import java.util.ArrayList; import java.util.List; /** * 定義一個查詢條件容器 * Created by gzs */ public class Criteria<T> implements Specification<T> { private List<Criterion> criterions = new ArrayList<>(); private List<Criterion> orders = new ArrayList<>(); @Override public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder builder) { if (!criterions.isEmpty()) { List<Predicate> predicates = new ArrayList<>(); for (Criterion c : criterions) { predicates.add(c.toPredicate(root, query, builder)); } for (Criterion c : orders) { Order order = c.toOrder(root, query, builder); query.orderBy(order); } // 將所有條件用 and 聯合起來 if (predicates.size() > 0) { return builder.and(predicates.toArray(new Predicate[predicates.size()])); } } return builder.conjunction(); } /** * 增加簡單條件表達式 * * @Methods Name add * @Create In 2018-10-15 By gzs */ public void add(Criterion criterion) { if (criterion != null) { criterions.add(criterion); } } /** * 增加排序表達式 * * @Methods Name add * @Create In 2018-11-15 By gzs */ public void addOrder(Criterion order) { if (order != null) { orders.add(order); } } }
2、條件表達式
package cn.aid.common.utils.jpa.condition; import javax.persistence.criteria.*; /** * 創建條件表達式接口,模擬系統的條件查詢 * Created by gzs */ public interface Criterion { enum Operator { EQ, NE, LIKE, GT, LT, GTE, LTE, AND, OR, IS_MEMBER, IS_NOT_MEMBER, DESC, ASC } Predicate toPredicate(Root<?> root, CriteriaQuery<?> query, CriteriaBuilder builder); Order toOrder(Root<?> root, CriteriaQuery<?> query, CriteriaBuilder builder); }
3、實現邏輯條件表達式
package cn.aid.common.utils.jpa.condition; import javax.persistence.criteria.*; import java.util.ArrayList; import java.util.List; /** * 邏輯條件表達式 用於複雜條件時使用,如單屬性多對應值的OR查詢等 * * Created by gzs */ public class LogicalExpression implements Criterion { /** * 邏輯表達式中包含的表達式 */ private Criterion[] criterion; /** * 計算符 */ private Operator operator; public LogicalExpression(Criterion[] criterions, Operator operator) { this.criterion = criterions; this.operator = operator; } @Override public Predicate toPredicate(Root<?> root, CriteriaQuery<?> query, CriteriaBuilder builder) { List<Predicate> predicates = new ArrayList<>(); for (int i = 0; i < this.criterion.length; i++) { predicates.add(this.criterion[i].toPredicate(root, query, builder)); } switch (operator) { case OR: return builder.or(predicates.toArray(new Predicate[predicates.size()])); default: return null; } } @Override public Order toOrder(Root<?> root, CriteriaQuery<?> query, CriteriaBuilder builder) { return null; } }
4、實現簡單條件表達式
package cn.aid.common.utils.jpa.condition; import org.springframework.util.StringUtils; import javax.persistence.criteria.*; import java.util.List; import java.util.Map; import java.util.Set; /** * 簡單條件表達式 * * Created by gzs */ public class SimpleExpression implements Criterion { /** * 屬性名 */ private String fieldName; /** * 對應值 */ private Object value; /** * 計算符 */ private Operator operator; protected SimpleExpression(String fieldName, Object value, Operator operator) { this.fieldName = fieldName; this.value = value; this.operator = operator; } @Override @SuppressWarnings({"rawtypes", "unchecked"}) public Predicate toPredicate(Root<?> root, CriteriaQuery<?> query, CriteriaBuilder builder) { Path expression; //此處是表關聯數據,注意僅限一層關聯,如user.address, //查詢user的address集合中,address的name爲某個值 if (fieldName.contains(".")) { String[] names = StringUtils.split(fieldName, "."); //獲取該屬性的類型,Set?List?Map? expression = root.get(names[0]); Class clazz = expression.getJavaType(); if (clazz.equals(Set.class)) { SetJoin setJoin = root.joinSet(names[0]); expression = setJoin.get(names[1]); } else if (clazz.equals(List.class)) { ListJoin listJoin = root.joinList(names[0]); expression = listJoin.get(names[1]); } else if (clazz.equals(Map.class)) { MapJoin mapJoin = root.joinMap(names[0]); expression = mapJoin.get(names[1]); } else { //是many to one時 expression = expression.get(names[1]); } } else { //單表查詢 expression = root.get(fieldName); } switch (operator) { case EQ: return builder.equal(expression, value); case NE: return builder.notEqual(expression, value); case LIKE: return builder.like((Expression<String>) expression, "%" + value + "%"); case LT: return builder.lessThan(expression, (Comparable) value); case GT: return builder.greaterThan(expression, (Comparable) value); case LTE: return builder.lessThanOrEqualTo(expression, (Comparable) value); case GTE: return builder.greaterThanOrEqualTo(expression, (Comparable) value); case IS_MEMBER: return builder.isMember(value, expression); case IS_NOT_MEMBER: return builder.isNotMember(value, expression); default: return null; } } @Override public Order toOrder(Root<?> root, CriteriaQuery<?> query, CriteriaBuilder builder) { return null; } }
5、實現排序表達式
package cn.aid.common.utils.jpa.condition; import org.springframework.util.StringUtils; import javax.persistence.criteria.*; import java.util.List; import java.util.Map; import java.util.Set; /** * 邏輯條件表達式 用於複雜條件時使用,如單屬性多對應值的OR查詢等 * * Created by gzs */ public class OrderExpression implements Criterion { /** * 計算符 */ private Operator operator; /** * 屬性名 */ private String fieldName; public OrderExpression(String fieldName, Operator operator) { this.fieldName = fieldName; this.operator = operator; } @Override public Predicate toPredicate(Root<?> root, CriteriaQuery<?> query, CriteriaBuilder builder) { return null; } @Override public Order toOrder(Root<?> root, CriteriaQuery<?> query, CriteriaBuilder builder) { Path expression; //此處是表關聯數據,注意僅限一層關聯,如user.address, //查詢user的address集合中,address的name爲某個值 if (fieldName.contains(".")) { String[] names = StringUtils.split(fieldName, "."); //獲取該屬性的類型,Set?List?Map? expression = root.get(names[0]); Class clazz = expression.getJavaType(); if (clazz.equals(Set.class)) { SetJoin setJoin = root.joinSet(names[0]); expression = setJoin.get(names[1]); } else if (clazz.equals(List.class)) { ListJoin listJoin = root.joinList(names[0]); expression = listJoin.get(names[1]); } else if (clazz.equals(Map.class)) { MapJoin mapJoin = root.joinMap(names[0]); expression = mapJoin.get(names[1]); } else { //是many to one時 expression = expression.get(names[1]); } } else { //單表查詢 expression = root.get(fieldName); } switch (operator) { case DESC: return builder.desc(expression); default: return builder.asc(expression); } } } 7、條件構造器
package cn.aid.common.utils.jpa.condition; import org.springframework.util.StringUtils; import java.util.Collection; /** * 條件構造器 * 用於創建條件表達式 * * Created by gzs */ public class Restrictions { /** * 等於 */ public static SimpleExpression eq(String fieldName, Object value, boolean ignoreNull) { if (ignoreNull && StringUtils.isEmpty(value)) { return null; } return new SimpleExpression(fieldName, value, Criterion.Operator.EQ); } /** * 集合包含某個元素 */ public static SimpleExpression hasMember(String fieldName, Object value, boolean ignoreNull) { if (ignoreNull && StringUtils.isEmpty(value)) { return null; } return new SimpleExpression(fieldName, value, Criterion.Operator.IS_MEMBER); } /** * 不等於 */ public static SimpleExpression ne(String fieldName, Object value, boolean ignoreNull) { if (ignoreNull && StringUtils.isEmpty(value)) { return null; } return new SimpleExpression(fieldName, value, Criterion.Operator.NE); } /** * 模糊匹配 */ public static SimpleExpression like(String fieldName, String value, boolean ignoreNull) { if (ignoreNull && StringUtils.isEmpty(value)) { return null; } return new SimpleExpression(fieldName, value, Criterion.Operator.LIKE); } /** */ // public static SimpleExpression like(String fieldName, String value, // MatchMode matchMode, boolean ignoreNull) { // if (StringUtils.isEmpty(value)) return null; // return null; // } /** * 大於 */ public static SimpleExpression gt(String fieldName, Object value, boolean ignoreNull) { if (ignoreNull && StringUtils.isEmpty(value)) { return null; } return new SimpleExpression(fieldName, value, Criterion.Operator.GT); } /** * 小於 */ public static SimpleExpression lt(String fieldName, Object value, boolean ignoreNull) { if (ignoreNull && StringUtils.isEmpty(value)) { return null; } return new SimpleExpression(fieldName, value, Criterion.Operator.LT); } /** * 小於等於 */ public static SimpleExpression lte(String fieldName, Object value, boolean ignoreNull) { if (ignoreNull && StringUtils.isEmpty(value)) { return null; } return new SimpleExpression(fieldName, value, Criterion.Operator.GTE); } /** * 大於等於 */ public static SimpleExpression gte(String fieldName, Object value, boolean ignoreNull) { if (ignoreNull && StringUtils.isEmpty(value)) { return null; } return new SimpleExpression(fieldName, value, Criterion.Operator.LTE); } /** * 降序 */ public static OrderExpression desc(String fieldName) { /*if (StringUtils.isEmpty(fieldName)) { return null; }*/ return new OrderExpression(fieldName, Criterion.Operator.DESC); } /** * 升序 */ public static OrderExpression asc(String fieldName) { /*if (StringUtils.isEmpty(fieldName)) { return null; }*/ return new OrderExpression(fieldName, Criterion.Operator.ASC); } /** * 並且 */ public static LogicalExpression and(Criterion... criterions) { return new LogicalExpression(criterions, Criterion.Operator.AND); } /** * 或者 */ public static LogicalExpression or(Criterion... criterions) { return new LogicalExpression(criterions, Criterion.Operator.OR); } /** * 包含於 */ @SuppressWarnings("rawtypes") public static LogicalExpression in(String fieldName, Collection value, boolean ignoreNull) { if (ignoreNull && (value == null || value.isEmpty())) { return null; } SimpleExpression[] ses = new SimpleExpression[value.size()]; int i = 0; for (Object obj : value) { ses[i] = new SimpleExpression(fieldName, obj, Criterion.Operator.EQ); i++; } return new LogicalExpression(ses, Criterion.Operator.OR); } /** * 集合包含某幾個元素,譬如可以查詢User類中Set<String> set包含"ABC","bcd"的User集合, * 或者查詢User中Set<Address>的Address的name爲"北京"的所有User集合 * 集合可以爲基本類型或者JavaBean,可以是one to many或者是@ElementCollection * @param fieldName * 列名 * @param value * 集合 * @return * expresssion */ public static LogicalExpression hasMembers(String fieldName, Object... value) { SimpleExpression[] ses = new SimpleExpression[value.length]; int i = 0; //集合中對象是基本類型,如Set<Long>,List<String> Criterion.Operator operator = Criterion.Operator.IS_MEMBER; //集合中對象是JavaBean if (fieldName.contains(".")) { operator = Criterion.Operator.EQ; } for (Object obj : value) { ses[i] = new SimpleExpression(fieldName, obj, operator); i++; } return new LogicalExpression(ses, Criterion.Operator.OR); } }
8、見證奇蹟的時刻來了demo
if (StringUtils.isNotBlank(teacher.getContactName())) { //動態查詢 Criteria<Teacher> criteria = new Criteria<>(); final LogicalExpression or = Restrictions.or( Restrictions.like("code", teacher.getContactName(), true), Restrictions.like("contactName", teacher.getContactName(), true), Restrictions.like("mobile", teacher.getContactName(), true)); criteria.add(or); criteria.add(Restrictions.eq("groupMerchantId", teacher.getGroupMerchantId(), true)); criteria.add(Restrictions.eq("merchantId", teacher.getMerchantId(), true)); criteria.add(Restrictions.eq("campusId", teacher.getCampusId(), true)); criteria.addOrder(Restrictions.desc("gmtModified")); Pageable pageable = new PageRequest(pageNo - 1, pageSize); //頁碼:前端從1開始,jpa從0開始,做個轉換 org.springframework.data.domain.Page<Teacher> cmsUsers = teacherRepository.findAll(criteria, pageable);