JPA 多条件、多表查询

JPA对于简单的查询操作确实很给力,但是涉及到多表、多条件、分页的场景就不是很好实现了。

可行的解决方案

1、多条件

public interface BaseRepository extends JpaRepository, JpaSpecificationExecutor

使用Specification来实现条件的拼接

2、多表

数据量不大的情况,可以考虑视图,视图实体配置和表的没有任何区别。

3、分页

可以自行实现分页逻辑,也可以使用框架的 Pageable 类。

核心代码示例

//	核心方法 拼接条件
	public default Predicate getPredocate(Root root, CriteriaQuery query, CriteriaBuilder cb,
			DataQueryObject dqo) {
		List predicates = new ArrayList<>();
//		获取查询对象的所有属性
		Field[] fields = dqo.getClass().getDeclaredFields();
		for (Field field : fields) {
			field.setAccessible(true);
			
			String queryFiled = null;
			QueryType queryType = null;
			Object value = null;
			Predicate predicate = null;
//			获取属性的 自定义注解类型
			QueryField annotaion = field.getAnnotation(QueryField.class);
//			如果没有注解 则跳过
			if(annotaion == null) {
				continue;
			}
//			如果注解中 name为空 则用字段名称作为属性名
			if(!StringUtils.isEmpty(annotaion.name())) {
				queryFiled = annotaion.name();
			} else {
				queryFiled = field.getName();
			}
			queryType = annotaion.type();
			try {
				value = field.get(dqo);
			} catch (IllegalArgumentException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			}
//			判断字段类型是否为空
			if(value == null && queryType.isNotCanBeNull()) {
				logger.debug("查询类型:" + queryType + "不允许为空。");
				continue;
			}
//			判断注解中 的条件类型
			switch (queryType) {
				case EQUAL:
					Path equal = getRootByQueryFiled(queryFiled, root);
					predicate = cb.equal(equal, value);
					predicates.add(predicate);
					break;
				case BEWTEEN:
					Path between = getRootByQueryFiledComparable(queryFiled, root);
					QueryBetween queryBetween = null;
					if(value instanceof QueryBetween) 
						queryBetween = (QueryBetween) value;
					else 
						continue;
					predicate = cb.between(between, queryBetween.after, queryBetween.before);
					predicates.add(predicate);
					break;
				case LESS_THAN:
					Path lessThan = getRootByQueryFiledComparable(queryFiled, root);
					if(value instanceof QueryBetween) 
						queryBetween = (QueryBetween) value;
					else 
						continue;
					predicate = cb.lessThan(lessThan, queryBetween.after);
					predicates.add(predicate);
					break;
				case LESS_THAN_EQUAL:
					Path lessThanOrEqualTo = getRootByQueryFiledComparable(queryFiled, root);
					if(value instanceof QueryBetween) 
						queryBetween = (QueryBetween) value;
					else 
						continue;
					predicate = cb.lessThanOrEqualTo(lessThanOrEqualTo, queryBetween.after);
					predicates.add(predicate);
					break;
				case GREATEROR_THAN:
					Path greaterThan = getRootByQueryFiledComparable(queryFiled, root);
					if(value instanceof QueryBetween) 
						queryBetween = (QueryBetween) value;
					else 
						continue;
					predicate = cb.greaterThan(greaterThan, queryBetween.after);
					predicates.add(predicate);
					break;
				case GREATEROR_THAN_EQUAL:
					Path greaterThanOrEqualTo = getRootByQueryFiledComparable(queryFiled, root);
					if(value instanceof QueryBetween) 
						queryBetween = (QueryBetween) value;
					else 
						continue;
					predicate = cb.lessThanOrEqualTo(greaterThanOrEqualTo, queryBetween.after);
					predicates.add(predicate);
					break;
				case NOT_EQUAL:
					Path notEqual = getRootByQueryFiled(queryFiled, root);
					predicate = cb.notEqual(notEqual, value);
					predicates.add(predicate);
					break;
				case IS_NULL:
					Path isNull = getRootByQueryFiled(queryFiled, root);
					predicate = cb.isNull(isNull);
					predicates.add(predicate);
					break;
				case IS_NOT_NULL:
					Path isNotNull = getRootByQueryFiled(queryFiled, root);
					predicate = cb.isNotNull(isNotNull);
					predicates.add(predicate);
					break;
				case LEFT_LIKE:
					Path leftLike = getRootByQueryFiledString(queryFiled, root);
					predicate = cb.like(leftLike, "%" + value.toString());
					predicates.add(predicate);
					break;
				case RIGHT_LIKE:
					Path rightLike = getRootByQueryFiledString(queryFiled, root);
					predicate = cb.like(rightLike, value.toString() + "%");
					predicates.add(predicate);
					break;
				case FULL_LIKE:
					Path fullLike = getRootByQueryFiledString(queryFiled, root);
					predicate = cb.like(fullLike, "%" + value.toString() + "%");
					predicates.add(predicate);
					break;
				case DEFAULT_LIKE:
					Path like = getRootByQueryFiledString(queryFiled, root);
					predicate = cb.like(like, value.toString());
					predicates.add(predicate);
					break;
				case NOT_LIKE:
					Path notLike = getRootByQueryFiledString(queryFiled, root);
					predicate = cb.like(notLike, value.toString());
					predicates.add(predicate);
					break;
				case IN:
					Path in = getRootByQueryFiled(queryFiled, root);
					In ins = cb.in(in);
					List inList = null;
					if(value instanceof List) {
						inList = (List) value;
					}
					for (Object object : inList) {
						ins.value(object);
					}
					predicates.add(ins);
					break;
				default:
					break;
			}
		}
//		如果 为空 代表  没有任何有效的条件
		if(predicates.size() == 0) {
			return cb.and();
		}
		Object[] list = predicates.toArray();
		Predicate[] t = new Predicate[predicates.size()];
		Predicate[] result = predicates.toArray(t);
		return cb.and(result);
	}

	public default Path getRootByQueryFiled(String queryFiled, Root root) {
		if(queryFiled.indexOf(".") < 0) {
			return root.get(queryFiled);
		} else {
			return getRootByQueryFiled(queryFiled.substring(queryFiled.indexOf(".") + 1, queryFiled.length()), root.get(queryFiled.substring(0, queryFiled.indexOf("."))));
		}
	}

	public default Path getRootByQueryFiled(String queryFiled, Path path) {
		if(queryFiled.indexOf(".") < 0) {
			return path.get(queryFiled);
		} else {
			return getRootByQueryFiled(queryFiled.substring(queryFiled.indexOf(".") + 1, queryFiled.length()), path.get(queryFiled.substring(0, queryFiled.indexOf("."))));
		}
	}
	
	public default Path getRootByQueryFiledString(String queryFiled, Root root) {
		if(queryFiled.indexOf(".") < 0) {
			return root.get(queryFiled);
		} else {
			return getRootByQueryFiledString(queryFiled.substring(queryFiled.indexOf(".") + 1, queryFiled.length()), root.get(queryFiled.substring(0, queryFiled.indexOf("."))));
		}
	}

	public default Path getRootByQueryFiledString(String queryFiled, Path path) {
		if(queryFiled.indexOf(".") < 0) {
			return path.get(queryFiled);
		} else {
			return getRootByQueryFiledString(queryFiled.substring(queryFiled.indexOf(".") + 1, queryFiled.length()), path.get(queryFiled.substring(0, queryFiled.indexOf("."))));
		}
	}
	
	public default Path getRootByQueryFiledComparable(String queryFiled, Root root) {
		if(queryFiled.indexOf(".") < 0) {
			return root.get(queryFiled);
		} else {
			return getRootByQueryFiledComparable(queryFiled.substring(queryFiled.indexOf(".") + 1, queryFiled.length()), root.get(queryFiled.substring(0, queryFiled.indexOf("."))));
		}
	}

	public default Path getRootByQueryFiledComparable(String queryFiled, Path path) {
		if(queryFiled.indexOf(".") < 0) {
			return path.get(queryFiled);
		} else {
			return getRootByQueryFiledComparable(queryFiled.substring(queryFiled.indexOf(".") + 1, queryFiled.length()), path.get(queryFiled.substring(0, queryFiled.indexOf("."))));
		}
	} 
  

 自定义注解

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface QueryField {
	QueryType type();
	String name() default "";
}

 接收参数

	@QueryField(type = QueryType.EQUAL, name = "redddlCode")
	@ApiModelProperty(value="XXX",name="redddlCode",example="S2344")
	private String redddlCode;

 

你可能感兴趣的:(Java)