spring-data-jpa 實現子查詢和複雜的關聯查詢總結

最近開發過程中,遇到了一個比較複雜的查詢功能,查詢條件有五六十個,每個條件可填可不填,要根據用戶的輸入條件查詢結果,並且根據用戶選中的字段返回對應的數據。

其中的查詢條件裏面大部分是 and的關係,有部分是互相之間是or的關係

所以查詢邏輯裏面牽扯到子查詢和關聯查詢

 

1、spring-data-jpa 要實現 子查詢,如下代碼所示可以實現

 //代碼打印出的sql代碼如下
/**
 *    from
 *         cat catdomain0_
 *     where
 *         catdomain0_.id in (
 *             select
 *                 hobby1_.cat_id
 *             from
 *                 hobby hobby1_
 *             where
 *                 (
 *                     hobby1_.cat_id in (
 *                         select
 *                             hobby2_.cat_id
 *                         from
 *                             hobby hobby2_
 *                         where
 *                             hobby2_.chinese=?
 *                     )
 *                 )
 *                 and hobby1_.type=1
 *             )
 */

//具體的實現代碼
 public static Specification<CatDomain> listAdvanceSpec() {
        return (Root<CatDomain> root, CriteriaQuery<?> query, CriteriaBuilder builder) -> {
            List<Predicate> predicates = new ArrayList<>();
            //完成子查詢

            Subquery subQuery = query.subquery(String.class);
            Root from = subQuery.from(Hobby.class);
            subQuery.select(from.get("catId")).where(builder.equal(from.get("chinese"), "ls"));

            Subquery subQuery11 = query.subquery(String.class);
            Root from1 = subQuery11.from(Hobby.class);
            subQuery11.select(from1.get("catId")).where(from1.get("catId").in(subQuery), builder.equal(from1.get("type"), "1"));
            return builder.and((root.get("id")).in(subQuery11));

        };
    }

2、spring-data-jpa 要實現如下關聯查詢

select a.*

from table_a a

left join table_b

//主要實現如下所示的自定義條件查詢b.status=1 等

on a.id=b.id and b.status=1 

where a.name="zs" and b.age=18

示例代碼如下:

  public static Specification<CatDomain> listQuerySpec() {
        return (Root<CatDomain> root, CriteriaQuery<?> query, CriteriaBuilder builder) -> {
            query.distinct(true);
            List<Predicate> predicates = new ArrayList<>();

            Join<Object, Object> hobby1 = root.join("hobby1", JoinType.INNER);
            // 此處相當於 left join table_b b 中 後面的on b.type=1 and b.name="zs"等,可填寫多個條件
            hobby1.on(builder.equal(hobby1.get("type"), "1"));


            Join<Object, Object> hobby2 = root.join("hobby2", JoinType.INNER);
            hobby2.on(builder.equal(hobby2.get("type"), "2"));

            predicates.add(builder.equal(hobby2.get("chinese"), "ls"));
            predicates.add(builder.isNotEmpty(root.get("hobby1")));

            predicates.add(builder.equal(hobby2.get("chinese"), "ls"));
            predicates.add(builder.isNotEmpty(root.get("hobby2")));
            // 返回Predicate
            return builder.and(predicates.toArray(new Predicate[predicates.size()]));
        };
    }

打印的sql 如下所示:

  from
        cat catdomain0_ 
    inner join
        hobby hobby1x1_ 
            on catdomain0_.id=hobby1x1_.cat_id 
            and catdomain0_.type1=hobby1x1_.type 
            and (
                hobby1x1_.type=1
            ) 
    inner join
        hobby hobby2x2_ 
            on catdomain0_.id=hobby2x2_.cat_id 
            and catdomain0_.type2=hobby2x2_.type 
            and (
                hobby2x2_.type=2
            ) 
    where
        hobby2x2_.chinese=? 
        and (
            exists (
                select
                    hobby1x3_.id 
                from
                    hobby hobby1x3_ 
                where
                    catdomain0_.id=hobby1x3_.cat_id 
                    and catdomain0_.type1=hobby1x3_.type
            )
        ) 
        and hobby2x2_.chinese=? 
        and (
            exists (
                select
                    hobby2x4_.id 
                from
                    hobby hobby2x4_ 
                where
                    catdomain0_.id=hobby2x4_.cat_id 
                    and catdomain0_.type2=hobby2x4_.type
            )
        )

 

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