Spring Data JPA帶條件分頁(yè)查詢實(shí)現(xiàn)原理
最新Spring Data JPA官方參考手冊(cè) Version 2.0.0.RC2,2017-07-25
https://docs.spring.io/spring-data/jpa/docs/2.0.0.RC2/reference/html/
JPA參考手冊(cè) (找了半天, 在線版的只找到這個(gè))
https://www.objectdb.com/java/jpa
Spring Data JPA的Specification類, 是按照Eric Evans的《領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)》書中Specification的概念和語(yǔ)義來(lái)定義查詢條件的API。
使用Spring Data JPA, 我們一般將自己的dao接口繼承CrudRepository接口和JpaSpecificationExecutor接口, 由框架生成代理類來(lái)完成具體的調(diào)用, 而不用自己寫daoImpl實(shí)現(xiàn)類, 因?yàn)檫@兩個(gè)接口自帶了很多方法, 如果我們寫實(shí)現(xiàn)類會(huì)發(fā)現(xiàn)一上來(lái)就需要實(shí)現(xiàn)十來(lái)個(gè)方法, 比較麻煩。
其中CrudRepository接口主要負(fù)責(zé)增/刪/改的操作, JpaSpecificationExecutor接口主要負(fù)責(zé)查詢的操作, 另外, 框架還支持在dao接口的方法名上定義一些簡(jiǎn)單的語(yǔ)義來(lái)進(jìn)行增刪改查, 底層會(huì)對(duì)應(yīng)地做具體實(shí)現(xiàn)。
那如何封裝具體的查詢條件呢?
在service層調(diào)用dao接口從JpaSpecificationExecutor繼承的抽象查詢方法, 它就會(huì)自動(dòng)讓你準(zhǔn)備相關(guān)實(shí)參, 其中Specification對(duì)象就是經(jīng)常用在條件查詢的方法的一個(gè)形參, 也就是說(shuō), 封裝查詢條件的過(guò)程轉(zhuǎn)移到service層了。
我們一般以匿名內(nèi)部類的方式new一個(gè)Specification對(duì)象, 實(shí)現(xiàn)其中的toPredicate方法, 舉個(gè)例子,
Specification<Person> specification = new Specification<Person>() {
@Override
public Predicate toPredicate(Root<Person> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
...
};
其中, Predicate, Root, CriteriaQuery, CriteriaBuilder都是javax.persistence包中的接口, 方法的這3個(gè)實(shí)參由框架交給我們。
Predicate意思是"描述語(yǔ)", 就是我們封裝完查詢條件后要交給Specification一個(gè)清楚的描述, 要怎么組合sql語(yǔ)句去查詢。
Root表示為泛型里的Person對(duì)象描述一個(gè)根位置, 可以從這個(gè)根位置去取該對(duì)象的屬性, 以及屬性的屬性, 類似對(duì)象導(dǎo)航的意思, 比如要取Person地址屬性的城市, 就可以root.get("address").get("city").as(String.class), 其返回值是一個(gè)Expression對(duì)象;
CriteriaQuery代表?xiàng)l件查詢,主要提供where、group by、having、order by等。
CriteriaBuilder用于構(gòu)造篩選條件,主要提供equal、and、or、lt、gt、between、like等, 以及獲得CriteriaQuery、CriteriaUpdate、CriteriaDelete對(duì)象。構(gòu)造每個(gè)篩選條件一般需要Expression類型作為實(shí)參, 可以通過(guò)Root對(duì)象調(diào)用get()方法得到。如果有多個(gè)篩選條件, 調(diào)用criteriaBuilder的and、or等方法連接起來(lái), 一般是鏈?zhǔn)秸{(diào)用的形式。
舉個(gè)簡(jiǎn)單的實(shí)際例子:
//帶條件的分頁(yè)查詢, 根據(jù)person的first_name和last_name進(jìn)行模糊查詢
//為了直觀, 假設(shè)兩個(gè)字段都存在且不為空串, 省掉非空判斷和對(duì)應(yīng)的處理
public Page<Person> findSearch(Person person, int page, int size) {
Specification<Person> specification = new Specification<Person>() {
@Override
public Predicate toPredicate(Root<Person> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
Predicate predicate1 = criteriaBuilder.like(root.get("first_name").as(String.class), "%"+person.getFirstName()+"%");
Predicate predicate2 = criteriaBuilder.like(root.get("last_name").as(String.class), "%"+person.getLastName()+"%");
Predicate finalPredicate = criteriaBuilder.and(predicate1, predicate2);
return finalPredicate;
}
};
PageRequest pageRequest = PageRequest.of(page-1, size);
return personDao.findAll(specification, pageRequest);
}
當(dāng)然這都是JPQL的語(yǔ)法了, 很多開(kāi)發(fā)者也經(jīng)常在dao接口中直接寫SQL語(yǔ)句來(lái)讓框架查詢, 使用起來(lái)感覺(jué)有點(diǎn)類似MyBatis, 會(huì)顯得清爽很多, 只需定義一個(gè)抽象方法加上對(duì)應(yīng)的注解@Modifying和@Query(value="sql語(yǔ)句", nativeQuery=true)即可, 它還有一個(gè)好處, 不用讓封裝查詢條件這種事情跑到service層去。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
SpringBoot?SpringSecurity?詳細(xì)介紹(基于內(nèi)存的驗(yàn)證)
這篇文章主要介紹了SpringBoot?SpringSecurity?介紹(基于內(nèi)存的驗(yàn)證),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-04-04
使用JAXBContext輕松實(shí)現(xiàn)Java和xml的互相轉(zhuǎn)換方式
這篇文章主要介紹了依靠JAXBContext輕松實(shí)現(xiàn)Java和xml的互相轉(zhuǎn)換方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-08-08
SpringBoot條件注解之@ConditionalOnClass等注解的使用場(chǎng)景分析
文章詳細(xì)介紹了SpringBoot中條件注解的體系,包括基本概念、@ConditionalOnClass等常用注解的工作原理和使用場(chǎng)景,文章還探討了條件注解的組合使用、實(shí)戰(zhàn)應(yīng)用以及最佳實(shí)踐,幫助開(kāi)發(fā)者更好地理解和應(yīng)用條件注解,實(shí)現(xiàn)更靈活和智能的應(yīng)用配置,感興趣的朋友一起看看吧2025-03-03
java阿拉伯?dāng)?shù)字轉(zhuǎn)中文數(shù)字
這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)阿拉伯?dāng)?shù)字轉(zhuǎn)換為中文數(shù)字,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-04-04
解析Java編程中設(shè)計(jì)模式的開(kāi)閉原則的運(yùn)用
這篇文章主要介紹了解析Java編程中設(shè)計(jì)模式的開(kāi)閉原則的運(yùn)用,開(kāi)閉原則多應(yīng)用于Java程序的擴(kuò)展開(kāi)發(fā)方面,需要的朋友可以參考下2016-02-02
java虛擬機(jī)jvm方法區(qū)實(shí)例講解
在本篇文章里小編給大家整理的是一篇關(guān)于java虛擬機(jī)jvm方法區(qū)實(shí)例講解內(nèi)容,有興趣的朋友們可以學(xué)習(xí)下。2021-02-02
Spring?Boot?使用斷言讓你的代碼在上線前就通過(guò)“體檢”(最新整理)
斷言是一種編程技巧,用于在代碼中插入檢查點(diǎn),驗(yàn)證程序的狀態(tài)是否符合預(yù)期,如果斷言失敗,程序會(huì)拋出一個(gè)錯(cuò)誤,幫助你快速發(fā)現(xiàn)和修復(fù)bug,本文給大家介紹Spring?Boot?斷言:讓你的代碼在上線前就通過(guò)“體檢”,感興趣的朋友一起看看吧2025-03-03
springboot控制層傳遞參數(shù)為非必填值的操作
這篇文章主要介紹了springboot控制層傳遞參數(shù)為非必填值的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-10-10
Java數(shù)據(jù)結(jié)構(gòu)之雙向鏈表的實(shí)現(xiàn)
相較單鏈表,雙向鏈表除了data與next域,還多了一個(gè)pre域用于表示每個(gè)節(jié)點(diǎn)的前一個(gè)元素。這樣做給雙向鏈表帶來(lái)了很多優(yōu)勢(shì)。本文主要介紹了雙向鏈表的實(shí)現(xiàn),需要的可以參考一下2022-10-10

