818 spring data jpa 一些接口與方法



spring jpa 主要分為三個類:
org.springframework.data.jpa.repository.JpaRepository<T, ID>
org.springframework.data.jpa.repository.JpaSpecificationExecutor<T>
org.springframework.data.repository.CrudRepository<T, ID>
這三個類的實現類都是
org.springframework.data.jpa.repository.support.SimpleJpaRepository<T, ID>(這個類挺牛逼的)
其中
JpaRepository主要是findall findpage findone這樣的方法
JpaSpecificationExecutor主要是findall(spec) findpage(spec) findone(spec)這樣的方法
spec-->查詢條件,需要接口org.springframework.data.jpa.domain.Specification<T>這個接口
並且實現
org.springframework.data.jpa.domain.Specification.toPredicate(Root<T>, CriteriaQuery<?>, CriteriaBuilder)
這個接口中有三個參數:
Root
CriteriaQuery
CriteriaBuilder
其中 Root是查詢結果的一個實體對象,也就是查詢結果返回的主要對象,其中一對多OR多對一就是從這個對象開始計算的,具體層級關系
javax.persistence.TupleElement<X>
javax.persistence.criteria.Selection<X>
javax.persistence.criteria.Expression<T>
javax.persistence.criteria.Path<X>
javax.persistence.criteria.From<Z, X>
javax.persistence.criteria.Root<X>
這幾個接口主要用於描述一個數據庫對象與實體對象的對應關系,就不多說了。
然后是javax.persistence.criteria.CriteriaQuery<T>,這個是JPA標准,主要是構建查詢條件的,里面的方法都是各種查詢方式:distinct、select、where、groupby、having、orderby這些方法,想必大家都知道這些是組件SQL語句的基本方法。
接下來是javax.persistence.criteria.CriteriaBuilder,這個接口主要是用來進行一些函數操作,不過我們這里先關注JPA標准中Hibernate的兩個實現方法:
1.and org.hibernate.ejb.criteria.CriteriaBuilderImpl.and(Predicate...)
2.or org.hibernate.ejb.criteria.CriteriaBuilderImpl.or(Predicate...)
這兩個方法都有一個關鍵的接口:Predicate(javax.persistence.criteria.Predicate);
這個接口,同為Expression(javax.persistence.criteria.Expression<Boolean>)的子接口,可以肯定也是字段相關的表達式,在實際操作中,這個接口也是作為關聯各種Predicate的核心操作接口,and方法是將各個條件作為and來拼接,進行查詢;or是將各條件作為or來拼接,進行查詢。
然后說如何生成一個Predicate接口,生成的核心類還是上面的CriteriaBuilder(javax.persistence.criteria.CriteriaBuilder),在這個接口中,很多方法都是返回Predicate接口的,其中包含between、gt(大於)、lt(小於)、not(非)等等操作,將所需要的這些查詢條件都放在一個array數組(或者采用java.util.ArrayList.toArray(T[])-->cb.and(predicateList.toArray(new Predicate[predicates.size()]))),然后調用上一步說的and或者or方法進行拼接,當然,如果一個查詢既有and又有or,用這種方式還沒有具體嘗試過,有待考證。
說了這么多,先總結一下
Specification的toPredicate這個方法聲明了
Root:查詢哪個表
CriteriaQuery:查詢哪些字段,排序是什么
CriteriaBuilder:字段之間是什么關系,如何生成一個查詢條件,每一個查詢條件都是什么方式
Predicate(Expression):單獨每一條查詢條件的詳細描述
這些,就是有條件查詢的使用方式,springJPA和hibernate的完美結合(如果只用springJPA,根本了解不到這里)
來個簡單的例子吧:
/** 查詢名字包含icarus,或者手機號包含188的用戶(如果return中的or改為and,就是查詢名字包含icarus,並且手機號包含188的用戶) */
// query = cb.createQuery(User.class);// query是這么出來的
List<Predicate> predicateList = new ArrayList<>();
root = query.from(User.class);
Path<String> nameExp = root.get("name");
Predicate p1 = cb.like(nameExp, "%icarus%");
Path<String> phoneExp = root.get("phone");
Predicate p2 = cb.like(phoneExp, "%188%");
predicateList.add(p1);
predicateList.add(p2);
return cb.or(predicateList.toArray(new Predicate[predicates.size()]));
如果想提煉抽象類,則需要將返回predicateList這個方法給抽象化,不過這時候就無法提供OR和AND雙重選擇了。
當然,通過其它參數判斷也可以,不過優勢也不大。
如果想通過判斷,推薦Predicate這個類里面的枚舉值AND和OR
在CriteriaBuilder中,還有asc、desc兩個方法,返回Order(此處order在CriteriaQuery中使用,和下面PageRequest說的order、sort不同);還有sum、count、avg、max、min這幾個方法,聚合函數理論上是返回值中才會出現的,這里出現,暫且還真不知道什么用處,不過肯定有用,還望高人指點一下。
以上,是關於springJPA在進行條件查詢時使用的方式。不能說簡單了,因為方法並沒有直接寫SQL的優勢,好的是跨平台,相信hibernate的誇數據庫執行是很給力的
P.S. 這種設計模式在以前做一個日本的項目時遇見過,每一個查詢條件都采用一個方法累加的手段,好的一方面是方法式增加查詢條件、不用管實現方式、可使用於不同的數據庫,針對專注java開發的程序員比較友好一些;壞處也很明顯,繁瑣、效率低,這些毋庸置疑,畢竟從HQL到SQL還需要很長的轉換。
還沒完,繼續
剛才只是說了條件查詢中的Specification,包含的內容相當多,然后再說下查詢結果相關的內容。
findall和findall(spec)這兩個方法比較簡單,返回對象是List<T>
其中T在findall中指定的是JpaRepository中的第一個泛型對象,
在findall(spec)中指定的是JpaSpecificationExecutor中的第一個泛型對象,
也就是與數據庫對應的實體類一樣(spec還應該和root對應,因為Specification也需要泛型,應該在寫Specification的時候就指定了)
findone和findone(spec)返回對象是T,T也同findall
額外在說一下findall(sort)和findall(pageable),其返回結果是org.springframework.data.domain.Page<T>
P.S.(因為findall(spec,sort)和findall(spec,pageable)和這兩個區別不是很大,就不在額外贅述了,自行理解吧)
在這里又出來兩個參數:sort和pageable
sort:實質就是一組order(此order不是上面CriteriaBuilder中通過asc和desc生成的order接口,而是sort的一個內部公開類(理解成一個普通類就行),是一個實現類),sort的生成可以使用一個order數組、order列表、屬性數組、屬性列表。采用order的好處是可以自定義排序方向(order由屬性和方向組成),若采用屬性,則默認使用ASC升序排列
說完了sort,我們再來說說pageable
pageable指的是org.springframework.data.domain.Pageable,這個接口有4個方法,
getPageNumber-->獲取頁碼
getPageSize -->分頁大小
getOffset -->偏移量
getSort -->獲取排序信息
對於pageable的產生,也很容易,采用org.springframework.data.domain.PageRequest這個實現類,將構造方法生成出來即可,沒有第二個實現類。將sort、pageNumber、getPageSize設置好即可
偏移量不允許設置,這個是在查詢的時候,通過計算頁碼和分頁大小進行自動設置的
對於方法返回值:Page,實現類org.springframework.data.domain.PageImpl<T>也很簡單,僅僅是在List的基礎上增加了總頁碼、總大小等一系列常用內容,看代碼即可
以下,是spring官方對jpa的文檔,英文能力不錯的可以閱讀原文。
 http://docs.spring.io/spring-data/jpa/docs/1.8.0.RELEASE/reference/html/ 
不過原文大多講的是應用方向的


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM