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();
}
};
}