JPA动态查询封装
Posted 浅夏丶未央
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JPA动态查询封装相关的知识,希望对你有一定的参考价值。
一、定义一个查询条件容器
/** * 定义一个查询条件容器 * * @param <T> */ public class Criteria<T> implements Specification<T> { private List<Criterion> criterions = new ArrayList<Criterion>(); public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder builder) { if (!criterions.isEmpty()) { List<Predicate> predicates = new ArrayList<Predicate>(); for(Criterion c : criterions){ predicates.add(c.toPredicate(root, query,builder)); } // 将所有条件用 and 联合起来 if (predicates.size() > 0) { return builder.and(predicates.toArray(new Predicate[predicates.size()])); } } return builder.conjunction(); } /** * 增加简单条件表达式 * @Methods Name add * @param */ public Criteria<T> add(Criterion criterion){ if(criterion!=null){ criterions.add(criterion); } return this; } }
二、条件接口
public interface Criterion { public enum Operator { EQ, NE, LIKE, GT, LT, GTE, LTE, AND, OR } public Predicate toPredicate(Root<?> root, CriteriaQuery<?> query, CriteriaBuilder builder); }
三、逻辑条件表达式,用于复杂条件时使用,如or或and
public class LogicalExpression implements Criterion { private Criterion[] criterion; // 逻辑表达式中包含的表达式 private Operator operator; //计算符 public LogicalExpression(Criterion[] criterions, Operator operator) { this.criterion = criterions; this.operator = operator; } public Predicate toPredicate(Root<?> root, CriteriaQuery<?> query, CriteriaBuilder builder) { List<Predicate> predicates = new ArrayList<Predicate>(); 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()])); case AND: return builder.and(predicates.toArray(new Predicate[predicates.size()])); default: return null; } } }
四、简单条件表达式
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; } public String getFieldName() { return fieldName; } public Object getValue() { return value; } public Operator getOperator() { return operator; } @SuppressWarnings({ "rawtypes", "unchecked" }) public Predicate toPredicate(Root<?> root, CriteriaQuery<?> query, CriteriaBuilder builder) { Path expression = null; if(fieldName.contains(".")){ String[] names = StringUtils.split(fieldName, "."); expression = root.get(names[0]); for (int i = 1; i < names.length; i++) { expression = expression.get(names[i]); } }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); default: return null; } } }
五、条件构造器,用于创建条件表达式
public class Restrictions { /** * 等于 * @param fieldName * @param value * @return */ public static SimpleExpression eq(String fieldName, Object value) { if(StringUtils.isEmpty(value))return null; return new SimpleExpression (fieldName, value, Criterion.Operator.EQ); } /** * 不等于 * @param fieldName * @param value * @return */ public static SimpleExpression ne(String fieldName, Object value) { if(StringUtils.isEmpty(value))return null; return new SimpleExpression (fieldName, value, Criterion.Operator.NE); } /** * 模糊匹配 * @param fieldName * @param value * @param * @return */ public static SimpleExpression like(String fieldName, String value) { if(StringUtils.isEmpty(value))return null; return new SimpleExpression (fieldName, value, Criterion.Operator.LIKE); } /** * 大于 * @param fieldName * @param value * @return */ public static SimpleExpression gt(String fieldName, Object value) { if(StringUtils.isEmpty(value))return null; return new SimpleExpression (fieldName, value, Criterion.Operator.GT); } /** * 小于 * @param fieldName * @param value * @return */ public static SimpleExpression lt(String fieldName, Object value) { if(StringUtils.isEmpty(value))return null; return new SimpleExpression (fieldName, value, Criterion.Operator.LT); } /** * 大于等于 * @param fieldName * @param value * @return */ public static SimpleExpression lte(String fieldName, Object value) { if(StringUtils.isEmpty(value))return null; return new SimpleExpression (fieldName, value, Criterion.Operator.LTE); } /** * 小于等于 * @param fieldName * @param value * @param * @return */ public static SimpleExpression gte(String fieldName, Object value) { if(StringUtils.isEmpty(value))return null; return new SimpleExpression (fieldName, value, Criterion.Operator.GTE); } /** * 并且 * @param criterions * @return */ public static LogicalExpression and(Criterion... criterions){ return new LogicalExpression(criterions, Criterion.Operator.AND); } /** * 或者 * @param criterions * @return */ public static LogicalExpression or(Criterion... criterions){ return new LogicalExpression(criterions, Criterion.Operator.OR); } /** * 包含于 * @param fieldName * @param value * @return */ @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); } /** * 不包含于 * @param fieldName * @param value * @return */ @SuppressWarnings("rawtypes") public static LogicalExpression notin(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.NE); i++; } return new LogicalExpression(ses, Criterion.Operator.AND); } /** * between * @param fieldName * @param object1 * @param object2 * @return */ public static LogicalExpression between(String fieldName, Object object1, Object object2) { if(object1 == null || object2 == null) { return null; } SimpleExpression[]ses=new SimpleExpression[2]; ses[0]=new SimpleExpression(fieldName,object1, Criterion.Operator.GTE); ses[1]=new SimpleExpression(fieldName,object2, Criterion.Operator.LTE); return new LogicalExpression(ses, Criterion.Operator.AND); }
六、构造动态查询仓库接口
public interface BaseRepository<T,ID extends Serializable> extends PagingAndSortingRepository<T,ID> { int count(Specification<T> specification); Page<T> findAll(Specification<T> specification, Pageable pageable); List<T> findAll(Specification<T> specification); }
使用实例:
POJO对象为
public class UserInfo { private Integer id; private String name; ... }
dao接口为
public interface UserInfoService extends BaseRepository<UserInfo,Integer> { }
使用:
@RunWith(SpringRunner.class) @SpringBootTest public class test { @Autowired private UserInfoService userInfoService; @Test public void test() { Criteria<UserInfo> criteria = new Criteria<>(); criteria.add(Restrictions.eq("id",10)).add(Restrictions.like("name","abc")); List<UserInfo> users = userInfoService.findAll(criteria); } }
以上是关于JPA动态查询封装的主要内容,如果未能解决你的问题,请参考以下文章