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

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

更新一下今天遇到用list入参的问题

在查询后加in即可

List<User> findByIdIn(List<String> id);

更新!辣鸡jpa越用感觉越麻烦,今天项目把springboot更到2.0以上版本了,jpa也一起更新了,2.0以上jpa把findOne给删掉了,findById返回值更改为Optional包装的对象,需要用get方法才能get到实际需要的对象如:

AdminEntity teacher = adminEntityRepository.findById(body.getTeacherId()).get();

而且在底层我们可以看到,当查询对象为空,是直接抛出错误的,并不会返回null,这里需要我们注意

public T get() {
        if (value == null) {
            throw new NoSuchElementException("No value present");
        }
        return value;
    }

如果还想保持原来的逻辑功能,要不就trycatch搞起来,要不就自己写一个findByIdEqual还有最快的是在findById后加上.orElse(null)(其实我想改源码但是适用性太低了)

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值