JPA查询or和and形式分页查询实现!
jpa分页查询不能完成or查询并且自动分页,该实例就是实现jpa的or和and查询并且自动分页的格式!
一、为什么需要使用该技术?
实现or和and类型的查询原生的sql语句如下:
select * from 表名(叫NB表) where 字段1 = 185 and (字段2(开始日期) between '2023-06-05 00:00:00' and '2023-06-06 00:00:00' ) or (字段3(结束日期) between '2023-06-05 00:00:00' and '2023-06-06 00:00:00' and 字段4 = true);
这样的sql实现了查询NB表,字段1等于185,开始日期在2023-06-05 00:00:00和2023-06-06 00:00:00这个区间内 ”或 “ 字段4等于真 “且” 结束日期 也在2023-06-05 00:00:00和2023-06-06 00:00:00这个区间内数据!原生的sql能够实现查询,但是无法实现分页,所以需要使用JPA复杂查询or和and连用代码实现!
二、代码实现
1.代码如下:
1.创建实体类:
实体类里面红色圈起来的部分是关联的另一张schoolDorm表中的信息!(ManyToOne有兴趣的可以去可以下!)
2.创建controller!
controller里面只是做了一个简单的引用!不做赘述了!
一个接收对象,一个分页表示加一个service层方法的引用!
3.创建service层,代码实现:
主要代码如下 可以直接用:
public Map<String,Object> queryAllWithPageable(NbUploadExceptionQueryCriteria res, Pageable pageable) {
//代码实现JPA复杂的or和and查询!
Specification<NbUploadException> specification = (root, query, cb) -> {
//1.判断必填条件不能为空!为空直接返回null
if(res.getUserId()==null && res.getSchoolId() == null){
return (javax.persistence.criteria.Predicate) PageUtil.toPage(null);
}
//2.统一格式,可以直接照抄
List<Predicate> predicates = new ArrayList<>();
//3.这里就是or连接,createTime在BeginTime和EndTime之间的 “或”resolveTime在BeginTime和EndTime之间 “且” isOK等于true
predicates.add(cb.or(cb.between(root.get("createTime"), res.getBeginTime(),res.getEndTime()),
cb.and(cb.equal(root.get("isOk"), true),cb.between(root.get("resolveTime"), res.getBeginTime(),res.getEndTime()))));
// 4.使用左连接查询(关联表作为条件需要使用到)
Join<NbUploadException, SchoolDorm> join = root.join("schoolDorm", JoinType.LEFT);
//5.添加姓名条件
if (res.getSchoolId() != null) {
//root相当于操作本张表的数据!
predicates.add(cb.equal(root.get("schoolId"), res.getSchoolId()));
}
if (res.getFloor() != null) {
//join是关联表的数据!
predicates.add(cb.equal(join.get("floor"), res.getFloor()));
}
if (res.getDormNum() != null) {
predicates.add(cb.equal(join.get("dormNum"), res.getDormNum()));
}
if (res.getImei() != null) {
predicates.add(cb.equal(root.get("imei"), res.getImei()));
}
return cb.and(predicates.toArray(new javax.persistence.criteria.Predicate[predicates.size()]));
};
//6.这里的格式是根据自己需求去转换的 我这里需要的是DTO的形式!
return PageUtil.toPage(NbUploadExceptionRepository.findAll(specification, pageable).map(NbUploadExceptionMapper::toDto));
}
代码中3的位置就相当于sql这句:
select * from 表名(叫NB表) where 字段1 = 185 and (字段2(开始日期) between '2023-06-05 00:00:00' and '2023-06-06 00:00:00' ) or (字段3(结束日期) between '2023-06-05 00:00:00' and '2023-06-06 00:00:00' and 字段4 = true);
总结
我觉得这个方法还是非常的有用!后面的开发任务总会遇到的!也让大部分的开发变得简单也不局限于JPA封装好的格式了,很nice ,希望本次分享对你有用!共同进步!