spring Data JPA大大的簡化了我們持久層的開發,但是實際應用中,我們還是需要動態查詢的。
創新互聯公司長期為上1000家客戶提供的網站建設服務,團隊從業經驗10年,關注不同地域、不同群體,并針對不同對象提供差異化的產品和服務;打造開放共贏平臺,與合作伙伴共同營造健康的互聯網生態環境。為洛扎企業提供專業的成都網站設計、成都網站建設,洛扎網站改版等技術服務。擁有十年豐富建站經驗和眾多成功案例,為您定制開發。
比如,前端有多個條件,這些條件很多都是可選的,那么后端的SQL,就應該是可以定制的,在使用hibernate的時候,可以通過判斷條件來拼接SQL(HQL),當然,Spring Data JPA在簡化我們開發的同時,也是提供了支持的。
通過實現Criteria二實現的動態查詢,需要我們的Repo接口繼承JpaSpecificationExecutor接口,這是個泛型接口。
然后查詢的時候,傳入動態查詢參數,分頁參數等即可。
使用起來很簡單,不過為了知其所以然,先介紹一下Criteria API。
Criteria API
如果編譯器能夠對查詢執行語法正確性檢查,那么對于 Java 對象而言該查詢就是類型安全的。Java™Persistence API (JPA) 的 2.0 版本引入了 Criteria API,這個 API 首次將類型安全查詢引入到 Java 應用程序中,并為在運行時動態地構造查詢提供一種機制。本文介紹如何使用 Criteria API 和與之密切相關的 Metamodel API 編寫動態的類型安全查詢。
在使用Spring Data JPA的時候,只要我們的Repo層繼承JpaSpecificationExecutor接口就可以使用Specification進行動態查詢了,我們先看下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個方法,方法的參數和返回值已經很明顯的表達了其意圖。其中的參數,Pageable和Sort應該是比較簡單的,分別是分頁參數和排序參數,而重點就是Specification參數,先看下這個接口的定義:
public interface Specification<T> { Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb); }
其中就一個方法,返回的是動態查詢的數據結構。
javax.persistence.criteria.Predicate toPredicate(javax.persistence.criteria.Root<T> root, javax.persistence.criteria.CriteriaQuery<?> query, javax.persistence.criteria.CriteriaBuilder cb);
這里使用的都是Java EE中的規范,具體實現本人采用的是Hibernate,當然也可以選擇其他實現了JPA規范的數據持久層框架。
這里需要再次回過頭看看Criteria API中的一些東西:
Criteria 查詢是以元模型的概念為基礎的,元模型是為具體持久化單元的受管實體定義的,這些實體可以是實體類,嵌入類或者映射的父類。
CriteriaQuery接口:代表一個specific的頂層查詢對象,它包含著查詢的各個部分,比如:select 、from、where、group by、order by等注意:CriteriaQuery對象只對實體類型或嵌入式類型的Criteria查詢起作用
Root接口:代表Criteria查詢的根對象,Criteria查詢的查詢根定義了實體類型,能為將來導航獲得想要的結果,它與SQL查詢中的FROM子句類似
1:Root實例是類型化的,且定義了查詢的FROM子句中能夠出現的類型。
2:查詢根實例能通過傳入一個實體類型給 AbstractQuery.from方法獲得。
3:Criteria查詢,可以有多個查詢根。
4:AbstractQuery是CriteriaQuery 接口的父類,它提供得到查詢根的方法。CriteriaBuilder接口:用來構建CritiaQuery的構建器對象Predicate:一個簡單或復雜的謂詞類型,其實就相當于條件或者是條件組合
其中支持的方法非常之強大,下面給出一個示例,大家可以參考一下,同樣的,可以根據示例,自己可以寫出更為復雜的查詢:
Repo接口:
public interface DevHREmpConstrastDao extends JpaRepository<DevHREmpConstrast, Long>,JpaSpecificationExecutor<DevHREmpConstrast>
查詢實例1:
/** * 條件查詢時動態組裝條件 */ 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>(); //機構 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)//如果太多就不管了這個條件了 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("")){ //處理時間 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)//如果太多就不管了這個條件了 predicates.add(root.<String>get("confirmUserId").in(userIds)); } return query.where(predicates.toArray(new Predicate[predicates.size()])).getRestriction(); } }; }
查詢實例2:
/** * 條件查詢時動態組裝條件 */ 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>(); //機構 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)//如果太多就不管了這個條件了 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("")){ //處理時間 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)//如果太多就不管了這個條件了 predicates.add(root.<String>get("confirmUserId").in(userIds)); } return query.where(predicates.toArray(new Predicate[predicates.size()])).getRestriction(); } }; }
然后調用dao層方法傳入where()方法返回的參數即可。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持創新互聯。
當前文章:SpringDataJPA中的動態查詢實例
網頁鏈接:http://vcdvsql.cn/article26/gjeejg.html
成都網站建設公司_創新互聯,為您提供小程序開發、外貿網站建設、建站公司、面包屑導航、全網營銷推廣、網站制作
聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯