Spring boot JPA的复杂查询

就很坑这个东西搞了一个下午的时间,终于搞会怎么用
对于想要查询 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));

这样就能轻松使用复杂查询了!!!!

上一篇:spring – 如何为QueryDslPredicateExecutor编写谓词


下一篇:在Java中将谓词作为lambda返回