spring-data-jpa之Specification使用exists和not exists

写在前面

spring-data-jpa是spring对hibernate框架的封装,如果你一开始熟悉的是mybatis,那么转到jpa可能会让你有些不适应。jpa的简单查询确实非常非常方便,但是对于复杂查询来说,jpa确实有点“复杂”。当然,你可以写原生sql,但是那样就违背了jpa操作对象、避免操作sql的出发点了。好,废话不多说,进入正题吧。

 

遇到的问题

原先是针对单表的列表查询操作,非常简单,所以就用了Specification来做:

return (root, query, criteriaBuilder) -> {
            List<Predicate> predicates = Lists.newArrayList();
           
            //一些查询条件,数量比较多
            if (deviceStatus != null && deviceStatus > 0) {
                //主要是这段,之前是单表的状态查询
                 if (DeviceFilterStatus.STOP_USE.getCode().equals(deviceStatus)) {
                    predicates.add(criteriaBuilder.equal(root.get("isUsing"),                         deviceStatus));
                } else {
                    predicates.add(criteriaBuilder.equal(root.get("online"), deviceStatus));
                }
            }
            Predicate[] predicateArr = new Predicate[predicates.size()];
            return criteriaBuilder.and(predicates.toArray(predicateArr));

        };

后来改了需求,查询逻辑有所改变,涉及到第二张表,而我又不想推翻重新写原生sql,那样效率比较低(懒),去百度上疯狂找,奈何没答案,也问了很多人,纷纷表示没有用过这样的写法。后来我去了spring官网看文档,发现:

官网只有一些简单例子,并没有复杂查询的介绍(可能得去看hibernate官网,不过我没去看)。

so.....只能自己摸索

结果

我找了一下CriteriaBuilder的方法,发现存在exists的方法,那么,接下来的问题就在于如何构建他的参数Subquery。

Subquery看字面意思是子查询,显然sql里面exists后面的查询得放在这里面做

事情有了转机,我发现第二个参数CriteriaQuery有构建子查询的方法

然后我通过这个构建出子查询

Subquery<DeviceAlarmEntity> subQuery = query.subquery(DeviceAlarmEntity.class);
                Root<DeviceAlarmEntity> subRoot = subQuery.from(XXX.class);
                //这里是子查询的条件,前者是自身的条件,后者是主表的关联条件,当然where方法的参
//数是个可变参数,可以根据自己需要加条件
                subQuery.where(criteriaBuilder.equal(subRoot.get("valid"), true), criteriaBuilder.equal(root.get("deviceId"), subRoot.get("deviceId")));
                //这句话不加会报错,因为他不知道你子查询要查出什么字段
                subQuery.select(subRoot.get("id"));

最后,把上面的子查询放进exists方法的参数就可以了,

如果是not exists,前面再嵌套not方法,下面是示例:

//exists
criteriaBuilder.exists(subQuery)

//not exists
criteriaBuilder.not(criteriaBuilder.exists(subQuery)

本文没什么深度,纯粹经验之谈,希望能帮助到有同样需求的你。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章