Spring Data JPA中的動(dòng)態(tài)查詢實(shí)例
spring Data JPA大大的簡(jiǎn)化了我們持久層的開發(fā),但是實(shí)際應(yīng)用中,我們還是需要?jiǎng)討B(tài)查詢的。
比如,前端有多個(gè)條件,這些條件很多都是可選的,那么后端的SQL,就應(yīng)該是可以定制的,在使用hibernate的時(shí)候,可以通過判斷條件來拼接SQL(HQL),當(dāng)然,Spring Data JPA在簡(jiǎn)化我們開發(fā)的同時(shí),也是提供了支持的。
通過實(shí)現(xiàn)Criteria二實(shí)現(xiàn)的動(dòng)態(tài)查詢,需要我們的Repo接口繼承JpaSpecificationExecutor接口,這是個(gè)泛型接口。
然后查詢的時(shí)候,傳入動(dòng)態(tài)查詢參數(shù),分頁(yè)參數(shù)等即可。
使用起來很簡(jiǎn)單,不過為了知其所以然,先介紹一下Criteria API。
Criteria API
如果編譯器能夠?qū)Σ樵儓?zhí)行語(yǔ)法正確性檢查,那么對(duì)于 Java 對(duì)象而言該查詢就是類型安全的。Java™Persistence API (JPA) 的 2.0 版本引入了 Criteria API,這個(gè) API 首次將類型安全查詢引入到 Java 應(yīng)用程序中,并為在運(yùn)行時(shí)動(dòng)態(tài)地構(gòu)造查詢提供一種機(jī)制。本文介紹如何使用 Criteria API 和與之密切相關(guān)的 Metamodel API 編寫動(dòng)態(tài)的類型安全查詢。
在使用Spring Data JPA的時(shí)候,只要我們的Repo層繼承JpaSpecificationExecutor接口就可以使用Specification進(jìn)行動(dòng)態(tài)查詢了,我們先看下JpaSpecificationExecutor接口:
public interface JpaSpecificationExecutor<T> { T findOne(Specification<T> spec); List<T> findAll(Specification<T> spec); Page<T> findAll(Specification<T> spec, Pageable pageable); List<T> findAll(Specification<T> spec, Sort sort); long count(Specification<T> spec); }
可以看到提供了5個(gè)方法,方法的參數(shù)和返回值已經(jīng)很明顯的表達(dá)了其意圖。其中的參數(shù),Pageable和Sort應(yīng)該是比較簡(jiǎn)單的,分別是分頁(yè)參數(shù)和排序參數(shù),而重點(diǎn)就是Specification參數(shù),先看下這個(gè)接口的定義:
public interface Specification<T> { Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb); }
其中就一個(gè)方法,返回的是動(dòng)態(tài)查詢的數(shù)據(jù)結(jié)構(gòu)。
javax.persistence.criteria.Predicate toPredicate(javax.persistence.criteria.Root<T> root, javax.persistence.criteria.CriteriaQuery<?> query, javax.persistence.criteria.CriteriaBuilder cb);
這里使用的都是Java EE中的規(guī)范,具體實(shí)現(xiàn)本人采用的是Hibernate,當(dāng)然也可以選擇其他實(shí)現(xiàn)了JPA規(guī)范的數(shù)據(jù)持久層框架。
這里需要再次回過頭看看Criteria API中的一些東西:
Criteria 查詢是以元模型的概念為基礎(chǔ)的,元模型是為具體持久化單元的受管實(shí)體定義的,這些實(shí)體可以是實(shí)體類,嵌入類或者映射的父類。
CriteriaQuery接口:代表一個(gè)specific的頂層查詢對(duì)象,它包含著查詢的各個(gè)部分,比如:select 、from、where、group by、order by等注意:CriteriaQuery對(duì)象只對(duì)實(shí)體類型或嵌入式類型的Criteria查詢起作用
Root接口:代表Criteria查詢的根對(duì)象,Criteria查詢的查詢根定義了實(shí)體類型,能為將來導(dǎo)航獲得想要的結(jié)果,它與SQL查詢中的FROM子句類似
1:Root實(shí)例是類型化的,且定義了查詢的FROM子句中能夠出現(xiàn)的類型。
2:查詢根實(shí)例能通過傳入一個(gè)實(shí)體類型給 AbstractQuery.from方法獲得。
3:Criteria查詢,可以有多個(gè)查詢根。
4:AbstractQuery是CriteriaQuery 接口的父類,它提供得到查詢根的方法。CriteriaBuilder接口:用來構(gòu)建CritiaQuery的構(gòu)建器對(duì)象Predicate:一個(gè)簡(jiǎn)單或復(fù)雜的謂詞類型,其實(shí)就相當(dāng)于條件或者是條件組合
其中支持的方法非常之強(qiáng)大,下面給出一個(gè)示例,大家可以參考一下,同樣的,可以根據(jù)示例,自己可以寫出更為復(fù)雜的查詢:
Repo接口:
public interface DevHREmpConstrastDao extends JpaRepository<DevHREmpConstrast, Long>,JpaSpecificationExecutor<DevHREmpConstrast>
查詢實(shí)例1:
/** * 條件查詢時(shí)動(dòng)態(tài)組裝條件 */ private Specification<DevHREmpConstrast> where( final String corg,final String name,final String type,final String date,final String checker){ return new Specification<DevHREmpConstrast>() { @Override public Predicate toPredicate(Root<DevHREmpConstrast> root, CriteriaQuery<?> query, CriteriaBuilder cb) { List<Predicate> predicates = new ArrayList<Predicate>(); //機(jī)構(gòu) if(corg!=null&&!corg.equals("")){ List<String> orgIds = organizationDao.findByName("%"+corg+"%"); if(orgIds.size()>0&&orgIds.size()<1000) predicates.add(root.<String>get("confirmOrgNo").in(orgIds));//confirmOrgNo } //名字 if(name!=null&&!name.equals("")){ List<String> userIds = userDao.findByName(name); if(userIds.size()>0&&userIds.size()<1000)//如果太多就不管了這個(gè)條件了 predicates.add(root.<String>get("hrUserName").in(userIds)); } //類型 if(type!=null&&!type.equals("")) predicates.add(cb.equal(root.<String>get("hrUpdateType"),type)); //日期 if(date!=null&&!date.equals("")){ //處理時(shí)間 SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); Date startDate; Date endDate; try { startDate = format.parse(date); } catch (ParseException e) { startDate = new Date(946656000000L);//2000 01 01 } endDate = startDate; Calendar calendar = Calendar.getInstance() ; calendar.setTime(endDate); calendar.add(Calendar.DATE, 1); endDate = calendar.getTime(); calendar = null; predicates.add(cb.between(root.<Date>get("insDate"),startDate,endDate)); } //審核人 if(checker!=null&&!checker.equals("")){ List<String> userIds = userDao.findByName(checker); if(userIds.size()>0&&userIds.size()<1000)//如果太多就不管了這個(gè)條件了 predicates.add(root.<String>get("confirmUserId").in(userIds)); } return query.where(predicates.toArray(new Predicate[predicates.size()])).getRestriction(); } }; }
查詢實(shí)例2:
/** * 條件查詢時(shí)動(dòng)態(tài)組裝條件 */ private Specification<DevHREmpConstrast> where( final String corg,final String name,final String type,final String date,final String checker){ return new Specification<DevHREmpConstrast>() { @Override public Predicate toPredicate(Root<DevHREmpConstrast> root, CriteriaQuery<?> query, CriteriaBuilder cb) { List<Predicate> predicates = new ArrayList<Predicate>(); //機(jī)構(gòu) if(corg!=null&&!corg.equals("")){ List<String> orgIds = organizationDao.findByName("%"+corg+"%"); if(orgIds.size()>0&&orgIds.size()<1000) predicates.add(root.<String>get("confirmOrgNo").in(orgIds));//confirmOrgNo } //名字 if(name!=null&&!name.equals("")){ List<String> userIds = userDao.findByName(name); if(userIds.size()>0&&userIds.size()<1000)//如果太多就不管了這個(gè)條件了 predicates.add(root.<String>get("hrUserName").in(userIds)); } //類型 if(type!=null&&!type.equals("")) predicates.add(cb.equal(root.<String>get("hrUpdateType"),type)); //日期 if(date!=null&&!date.equals("")){ //處理時(shí)間 SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); Date startDate; Date endDate; try { startDate = format.parse(date); } catch (ParseException e) { startDate = new Date(946656000000L);//2000 01 01 } endDate = startDate; Calendar calendar = Calendar.getInstance() ; calendar.setTime(endDate); calendar.add(Calendar.DATE, 1); endDate = calendar.getTime(); calendar = null; predicates.add(cb.between(root.<Date>get("insDate"),startDate,endDate)); } //審核人 if(checker!=null&&!checker.equals("")){ List<String> userIds = userDao.findByName(checker); if(userIds.size()>0&&userIds.size()<1000)//如果太多就不管了這個(gè)條件了 predicates.add(root.<String>get("confirmUserId").in(userIds)); } return query.where(predicates.toArray(new Predicate[predicates.size()])).getRestriction(); } }; }
然后調(diào)用dao層方法傳入where()方法返回的參數(shù)即可。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Java mysql數(shù)據(jù)庫(kù)并進(jìn)行內(nèi)容查詢實(shí)例代碼
這篇文章主要介紹了Java mysql數(shù)據(jù)庫(kù)并進(jìn)行內(nèi)容查詢實(shí)例代碼的相關(guān)資料,需要的朋友可以參考下2016-11-11Java注解之Retention、Documented、Inherited介紹
這篇文章主要介紹了Java注解之Retention、Documented、Inherited注解介紹,本文內(nèi)容和相關(guān)文章是系列文章,需要的朋友可以參考下2014-09-09Java數(shù)據(jù)結(jié)構(gòu)之加權(quán)無向圖的設(shè)計(jì)實(shí)現(xiàn)
加權(quán)無向圖是一種為每條邊關(guān)聯(lián)一個(gè)權(quán)重值或是成本的圖模型。這種圖能夠自然地表示許多應(yīng)用。這篇文章主要介紹了加權(quán)無向圖的設(shè)計(jì)與實(shí)現(xiàn),感興趣的可以了解一下2022-11-11Java8中List轉(zhuǎn)Map(Collectors.toMap) 的技巧分享
在最近的工作開發(fā)之中,慢慢習(xí)慣了很多Java8中的Stream的用法,很方便而且也可以并行的去執(zhí)行這個(gè)流,這篇文章主要給大家介紹了關(guān)于Java8中List轉(zhuǎn)Map(Collectors.toMap) 的相關(guān)資料,需要的朋友可以參考下2021-07-07關(guān)于Https協(xié)議和HttpClient的實(shí)現(xiàn)詳解
這篇文章主要給大家介紹了關(guān)于Https協(xié)議和HttpClient實(shí)現(xiàn)的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2018-05-05JAVA?ImageIO.read方法報(bào)錯(cuò)/無效問題及解決
這篇文章主要介紹了JAVA?ImageIO.read方法報(bào)錯(cuò)/無效問題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-11-11maven打包插件的使用(maven-compiler-plugin、maven-dependency-plugin、m
本文主要介紹了maven打包插件的使用(maven-compiler-plugin、maven-dependency-plugin、maven-jar-plugin、maven-resources-plugin),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-06-06詳解mybatis中association和collection的column傳入多個(gè)參數(shù)問題
這篇文章主要介紹了詳解mybatis中association和collection的column傳入多個(gè)參數(shù)問題,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-10-10Springboot中如何使用Redisson實(shí)現(xiàn)分布式鎖淺析
redisson是redis的java客戶端程序,國(guó)內(nèi)外很多公司都有在用,下面這篇文章主要給大家介紹了關(guān)于Springboot中如何使用Redisson實(shí)現(xiàn)分布式鎖的相關(guān)資料,需要的朋友可以參考下2021-10-10