就很坑这个东西搞了一个下午的时间,终于搞会怎么用
对于想要查询 A and (B or C )或者 A And B And (C or D)
在jpa里你不能直接用and和or把字段拼起来,因为他并不会帮你自动加上括号,经过一下午的努力,学到了两种方法,但是我只用了其中一种,另一种感觉emmm挺复杂的而且效率和复用性都很差,就没去用。
1.这里我把差不多的两种都放在这里,首先是自己用QUERY注释写sql语句,这个复用性也很差好吧。然后差不多的就是,重新拼字段起来,把A and (B or C )变成A And B or A And C,就是把括号去掉就能直接使用,当然我遇到的情况是多条件判断查询的,这两种明显不符合我的要求,要写太多冗杂代码了,不符合自己完美主义hhhhhh
2.在JPA里可以使用Specification这个东西来对查询加入条件,我称他为条件构造器,具体使用:
Page<Entity> findAll(Specification<DeviceEntity> specification, Pageable pageable);
//实现自定义复杂条件和分页
然后在使用的时候,新建一个条件构造器,重写他的toPredicate方法,就能构造你想要的条件了。其中Predicate我理解为条件,围绕Predicate进行构造
EntityRepository.findAll(new Specification<DeviceEntity>() {
@Override
public Predicate toPredicate(Root<DeviceEntity> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
List<Predicate> list = new ArrayList<>();
Predicate predicateOr1 = criteriaBuilder.like(root.get("mac").as(String.class), "%" + finalSearch + "%");
Predicate predicateOr2 = criteriaBuilder.like(root.get("name").as(String.class), "%" + finalSearch + "%");
//构造or条件
Predicate predicateOr = criteriaBuilder.or(predicateOr1, predicateOr2);
//打上括号合并or语句
switch (admin.getType()) {
case 0:
break;
case 1:
list.add(criteriaBuilder.equal(root.get("pId").as(Long.class), admin.getId()));
break;
case 2:
list.add(criteriaBuilder.equal(root.get("sId").as(Long.class), admin.getId()));
break;
default:
return null;
}
//equal 为等于,Predicate条件中还提供了sql语句中如like等关键字,通过使用不同关键字的方法实现不同的功能
switch (status) {
case 0:
break;
case 1:
list.add(criteriaBuilder.equal(root.get("status").as(Integer.class), 1));
break;
case 2:
list.add(criteriaBuilder.equal(root.get("status").as(Integer.class), 3));
break;
default:
return null;
}
Predicate predicateAnd;//构造and条件
if (!list.isEmpty()) {
predicateAnd = criteriaBuilder.and(list.toArray(new Predicate[list.size()]));
criteriaQuery.where(predicateOr, predicateAnd);
}else {
criteriaQuery.where(predicateOr);
}
//当你使用where的时候就已经把条件放进你的查询操作中了,因此不需要返回构造器给前面
return null;
}
},new PageRequest(page - 1, size));
这样就能轻松使用复杂查询了!!!!