Spring Data JPA 只要定义好接口就能访问对应的数据了,非常的简洁,但在实际应用中,我们有复杂的 可选 查询条件,还是需要动态查询,实际上就是手写Where查询。

只要我们的Repo层继承JpaSpecificationExecutor接口就可以使用Specification进行动态查询了:

@Repository
public interface LogRepository extends JpaRepository<Log, Long>, JpaSpecificationExecutor<Log> {}

后台的操作日志,查询条件:可能以操作者或IP或操作时间或操作类型等等条件来组合查询,直接上代码

	/**
	 * 查询日志
	 */
	public Page<Log> getLogs(String username, String operation, String ip, Date startTime, Date endTime, int page) {
		return logRepository.findAll(where(username, operation, ip, startTime, endTime), new PageRequest(page, PageConstant.MAX_SIZE, new Sort(Sort.Direction.DESC, "id")));
	}

	/**
	 * 条件查询时动态组装条件
	 */
	Specification<Log> where(String username, String operation, String ip, Date startTime, Date endTime) {
		return new Specification<Log>() {
			@Override
			public Predicate toPredicate(Root<Log> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				List<Predicate> predicates = new ArrayList<Predicate>();
				// 账号
				if (!StringUtils.isEmpty(username)) {
					predicates.add(cb.equal(root.<String> get("username"), username));
				}

				// 操作类型
				if (!StringUtils.isEmpty(operation)) {
					final LogClassify classify = LogClassify.valueOf(operation);
					predicates.add(cb.in(root.get("operation")).value(Arrays.stream(OperationType.values()).filter(v -> v.getClassify() == classify).map(v -> v.name()).collect(Collectors.toList())));
				}

				// IP
				if (!StringUtils.isEmpty(ip)) {
					predicates.add(cb.equal(root.<String> get("ip"), ip));
				}

				// 日期
				if (startTime != null && endTime != null) {
					predicates.add(cb.between(root.<Date> get("createTime"), startTime, endTime));
				}

				return query.where(predicates.toArray(new Predicate[predicates.size()])).getRestriction();
			}
		};
	}

转载请注明原地址: http://blog.noark.xyz/article/2017/8/14/jpa之动态查询/