spring data jpa的动态查询封装

最近使用spring data jpa做了两个项目,对于动态查询的不友好做了个类似hibernate的封装,记录也分享下

首先定义一个所有条件的容器,继承Specification

/**
 * 定义一个查询条件容器
 * @author lee
 *
 * @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
	 * @Create In 2012-2-8 By lee
	 * @param expression0 void
	 */
	public void add(Criterion criterion){
		if(criterion!=null){
			criterions.add(criterion);
		}
	}
}

 然后是各种条件组装类,我首先做了一个接口来包装各种条件

/**
 * 条件接口
 * 用户提供条件表达式接口
 * @Class Name Criterion
 * @Author lee
 * @Create In 2012-2-8
 */
public interface Criterion {
	public enum Operator {
		EQ, NE, LIKE, GT, LT, GTE, LTE, AND, OR
	}
	public Predicate toPredicate(Root<?> root, CriteriaQuery<?> query,
			CriteriaBuilder builder);
}

 然后是针对不同类型条件处理的实现

一个是简单比较类型的处理

 

/**
 * 简单条件表达式
 * @author lee
 *
 */
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;
		}
	}
	
}

 一个逻辑条件计算实现

/**
 * 逻辑条件表达式 用于复杂条件时使用,如但属性多对应值的OR查询等
 * @author lee
 *
 */
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()]));
		default:
			return null;
		}
	}

}

 添加一个组装工厂类

/**
 * 条件构造器
 * 用于创建条件表达式
 * @Class Name Restrictions
 * @Author lee
 */
public class Restrictions {

	/**
	 * 等于
	 * @param fieldName
	 * @param value
	 * @param ignoreNull
	 * @return
	 */
	public static SimpleExpression eq(String fieldName, Object value, boolean ignoreNull) {
		if(StringUtils.isEmpty(value))return null;
		return new SimpleExpression (fieldName, value, Operator.EQ);
	}
	
	/**
	 * 不等于
	 * @param fieldName
	 * @param value
	 * @param ignoreNull
	 * @return
	 */
	public static SimpleExpression ne(String fieldName, Object value, boolean ignoreNull) {
		if(StringUtils.isEmpty(value))return null;
		return new SimpleExpression (fieldName, value, Operator.NE);
	}

	/**
	 * 模糊匹配
	 * @param fieldName
	 * @param value
	 * @param ignoreNull
	 * @return
	 */
	public static SimpleExpression like(String fieldName, String value, boolean ignoreNull) {
		if(StringUtils.isEmpty(value))return null;
		return new SimpleExpression (fieldName, value, Operator.LIKE);
	}

	/**
	 * 
	 * @param fieldName
	 * @param value
	 * @param matchMode
	 * @param ignoreNull
	 * @return
	 */
	public static SimpleExpression like(String fieldName, String value,
			MatchMode matchMode, boolean ignoreNull) {
		if(StringUtils.isEmpty(value))return null;
		return null;
	}

	/**
	 * 大于
	 * @param fieldName
	 * @param value
	 * @param ignoreNull
	 * @return
	 */
	public static SimpleExpression gt(String fieldName, Object value, boolean ignoreNull) {
		if(StringUtils.isEmpty(value))return null;
		return new SimpleExpression (fieldName, value, Operator.GT);
	}

	/**
	 * 小于
	 * @param fieldName
	 * @param value
	 * @param ignoreNull
	 * @return
	 */
	public static SimpleExpression lt(String fieldName, Object value, boolean ignoreNull) {
		if(StringUtils.isEmpty(value))return null;
		return new SimpleExpression (fieldName, value, Operator.LT);
	}

	/**
	 * 大于等于
	 * @param fieldName
	 * @param value
	 * @param ignoreNull
	 * @return
	 */
	public static SimpleExpression lte(String fieldName, Object value, boolean ignoreNull) {
		if(StringUtils.isEmpty(value))return null;
		return new SimpleExpression (fieldName, value, Operator.GTE);
	}

	/**
	 * 小于等于
	 * @param fieldName
	 * @param value
	 * @param ignoreNull
	 * @return
	 */
	public static SimpleExpression gte(String fieldName, Object value, boolean ignoreNull) {
		if(StringUtils.isEmpty(value))return null;
		return new SimpleExpression (fieldName, value, Operator.LTE);
	}

	/**
	 * 并且
	 * @param criterions
	 * @return
	 */
	public static LogicalExpression and(Criterion... criterions){
		return new LogicalExpression(criterions, Operator.AND);
	}
	/**
	 * 或者
	 * @param criterions
	 * @return
	 */
	public static LogicalExpression or(Criterion... criterions){
		return new LogicalExpression(criterions, 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,Operator.EQ);
			i++;
		}
		return new LogicalExpression(ses,Operator.OR);
	}
}

 使用方法如下

Criteria<Event> c = new Criteria<Event>();
c.add(Restrictions.like("code", searchParam.getCode(), true));
        c.add(Restrictions.eq("level", searchParam.getLevel(), false));
        c.add(Restrictions.eq("mainStatus", searchParam.getMainStatus(), true));
        c.add(Restrictions.eq("flowStatus", searchParam.getFlowStatus(), true));
        c.add(Restrictions.eq("createUser.userName", searchParam.getCreateUser(), true));
        c.add(Restrictions.lte("submitTime", searchParam.getStartSubmitTime(), true));
        c.add(Restrictions.gte("submitTime", searchParam.getEndSubmitTime(), true));
        c.add(Restrictions.eq("needFollow", searchParam.getIsfollow(), true));
        c.add(Restrictions.ne("flowStatus", CaseConstants.CASE_STATUS_DRAFT, true));
        c.add(Restrictions.in("solveTeam.code",teamCodes, true));
eventDao.findAll(c);

 其中eventDao为继承JpaSpecificationExecutor的接口类

你可能感兴趣的:(spring)