最近開發過程中,遇到了一個比較複雜的查詢功能,查詢條件有五六十個,每個條件可填可不填,要根據用戶的輸入條件查詢結果,並且根據用戶選中的字段返回對應的數據。
其中的查詢條件裏面大部分是 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
)
)