使用Spring Data Jpa的CriteriaQuery一個陷阱
使用Spring Data Jpa的CriteriaQuery進(jìn)行動態(tài)條件查詢時,可能會遇到一個陷阱,當(dāng)條件為空時,查詢不到任何結(jié)果,并不是期望的返回所有結(jié)果。這是為什么呢?
例如下述代碼,當(dāng)predicates為空時,返回結(jié)果總是為空。
public Page<VmhostWithRelationPO> listVmhostSpecWithRelationByPage(String name) {
Specification<VmhostWithRelationPO> spec = (root, cq, cb) -> {
root.join("user", JoinType.LEFT);
root.join("tenant", JoinType.LEFT);
List<javax.persistence.criteria.Predicate> predicates = new ArrayList<>();
......
return cb.or(predicates.toArray(new javax.persistence.criteria.Predicate[0]));
};
PageRequest pagable = PageRequest.of(0, 5);
Page<VmhostWithRelationPO> page = vmhostSpecWithRelationDao.findAll(spec, pagable);
return page;
}
看下or的注釋就明白了,因?yàn)榭諚l件總是為false,而and的空條件總是為true。所以,如果最后是and就沒有問題,只有or的時候有問題。
public interface CriteriaBuilder {
/**
* Create a conjunction of the given restriction predicates.
* A conjunction of zero predicates is true.
* @param restrictions zero or more restriction predicates
* @return and predicate
*/
Predicate and(Predicate... restrictions);
/**
* Create a disjunction of the given restriction predicates.
* A disjunction of zero predicates is false.
* @param restrictions zero or more restriction predicates
* @return or predicate
*/
Predicate or(Predicate... restrictions);
}
所以正確的寫法應(yīng)該這樣:
public Page<VmhostWithRelationPO> listVmhostSpecWithRelationByPage(String name) {
Specification<VmhostWithRelationPO> spec = (root, cq, cb) -> {
root.join("user", JoinType.LEFT);
root.join("tenant", JoinType.LEFT);
List<javax.persistence.criteria.Predicate> predicates = new ArrayList<>();
......
return predicates.isEmpty() ? cb.conjunction() : cb.or(predicates.toArray(new javax.persistence.criteria.Predicate[0]));
};
PageRequest pagable = PageRequest.of(0, 5);
Page<VmhostWithRelationPO> page = vmhostSpecWithRelationDao.findAll(spec, pagable);
return page;
}
如果條件為空則返回一個空conjunction,也就是空的and,總是為true。
公司項(xiàng)目的代碼中常見這種寫法:
public Page<VmhostWithRelationPO> listVmhostSpecWithRelationByPage(String name) {
Specification<VmhostWithRelationPO> spec = (root, cq, cb) -> {
root.join("user", JoinType.LEFT);
root.join("tenant", JoinType.LEFT);
List<javax.persistence.criteria.Predicate> predicates = new ArrayList<>();
......
if (predicates.isEmpty()) {
cq.where();
} else {
cq.where(cb.or(predicates.toArray(new javax.persistence.criteria.Predicate[0])));
}
return cq.getRestriction();
};
PageRequest pagable = PageRequest.of(0, 5);
Page<VmhostWithRelationPO> page = vmhostSpecWithRelationDao.findAll(spec, pagable);
return page;
}
也能正常工作,但是其實(shí)沒有必要在toPredicate方法中調(diào)用where,toPredicate只需要返回條件,外層會調(diào)用where。
public interface Specification<T> extends Serializable {
/**
* Creates a WHERE clause for a query of the referenced entity in form of a {@link Predicate} for the given
* {@link Root} and {@link CriteriaQuery}.
*
* @param root must not be {@literal null}.
* @param query must not be {@literal null}.
* @param criteriaBuilder must not be {@literal null}.
* @return a {@link Predicate}, may be {@literal null}.
*/
@Nullable
Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder);
}
本文作者: 鐘潘
本文鏈接: http://zhongpan.tech/2020/07/20/035-a-trap-for-using-criteriaquery/
以上就是CriteriaQuery使用的一個陷阱的詳細(xì)內(nèi)容,更多關(guān)于CriteriaQuery 陷阱的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
springboot 使用QQ郵箱發(fā)送郵件的操作方法
這篇文章主要介紹了springboot使用QQ郵箱發(fā)送郵件功能,本文通過實(shí)例圖文相結(jié)合給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-10-10
maven插件spring-boot-starter-tomcat的使用方式
這篇文章主要介紹了maven插件spring-boot-starter-tomcat的使用方式,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-07-07
使用Spring Batch實(shí)現(xiàn)批處理任務(wù)的詳細(xì)教程
在企業(yè)級應(yīng)用中,批處理任務(wù)是不可或缺的一部分,它們通常用于處理大量數(shù)據(jù),如數(shù)據(jù)遷移、數(shù)據(jù)清洗、生成報(bào)告等,Spring Batch是Spring框架的一部分,本文將介紹如何使用Spring Batch與SpringBoot結(jié)合,構(gòu)建和管理批處理任務(wù),需要的朋友可以參考下2024-06-06
Java報(bào)錯:Java.io.FileNotFoundException解決方法
這篇文章主要介紹了Java.io.FileNotFoundException的產(chǎn)生原因和解決方法,造成這個報(bào)錯的原因可能有文件路徑錯誤、文件被刪除或移動和權(quán)限問題,文中將解決的辦法介紹的非常詳細(xì),需要的朋友可以參考下2024-12-12
關(guān)于批量插入或更新數(shù)據(jù)(MyBatis-plus框架)
這篇文章主要介紹了關(guān)于批量插入或更新數(shù)據(jù)(MyBatis-plus框架),具有很好的參考價(jià)值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-09-09
Java發(fā)送郵箱驗(yàn)證碼、session校驗(yàn)功能
本篇主要描述“發(fā)送郵箱驗(yàn)證碼、session校驗(yàn)”相關(guān)前(html\js)后(java)臺代碼,業(yè)務(wù)邏輯示例,需要的朋友可以參考下2018-02-02

