一. 背景相關
JDK:1.8
IDE:IntelliJ IDEA
db:MYSQL
Spring Boot 結合 JPA
Spring Boot版本:v2.0.2.RELEASE
使用maven管理jar包
二:POMhtml
1 <dependencies> 2 <dependency> 3 <groupId>org.springframework.boot</groupId> 4 <artifactId>spring-boot-starter-test</artifactId> 5 <scope>test</scope> 6 </dependency> 7 <!--JPA--> 8 <dependency> 9 <groupId>org.springframework.boot</groupId> 10 <artifactId>spring-boot-starter-data-jpa</artifactId> 11 </dependency> 12 <!--熱部署--> 13 <dependency> 14 <groupId>org.springframework.boot</groupId> 15 <artifactId>spring-boot-devtools</artifactId> 16 <scope>runtime</scope> 17 <optional>true</optional> 18 </dependency> 19 <!--MySql數據庫--> 20 <dependency> 21 <groupId>mysql</groupId> 22 <artifactId>mysql-connector-java</artifactId> 23 <scope>runtime</scope> 24 </dependency> 25 <!--Pageable使用QPageRequest須要這個--> 26 <dependency> 27 <groupId>com.querydsl</groupId> 28 <artifactId>querydsl-jpa</artifactId> 29 </dependency> 30 </dependencies> 31 32 <build> 33 <plugins> 34 <plugin> 35 <groupId>org.springframework.boot</groupId> 36 <artifactId>spring-boot-maven-plugin</artifactId> 37 <configuration> 38 <fork>true</fork> 39 </configuration> 40 </plugin> 41 </plugins> 42 </build>
三:材料準備
兩張實體表 teacher、studnett
java
1 @Entity 2 @Table(name = "student") 3 public class Student { 4 5 @Id 6 @GeneratedValue 7 private Long id; 8 @Column(name = "stu_name") 9 private String stuName; 10 11 ....
注意: get、set方法自行完善
四. 主要總結內容
(1)Repository
(2)CrudRepository
(3)PagingAndSortingRepository
(4)JpaRepository
(5)JpaSpecificationExecutor
1. repository繼承圖示
mysql
繼承關係是:
JpaRepository 繼承PagingAndSortingRepository,PagingAndSortingRepository繼承CrudRepository,CrudRepository繼承Repository
能夠看出:
(1)都是接口
(2)上面的的繼承關係中並無JpaSpecificationExecutor,這個是獨立的
2. Repository接口
先點進去,看看,是一個空接口,也就是一個標記接口
spring
繼承這個接口能幹什麼?查詢
知足其必定的命名規範去書寫方法名,能夠不用本身寫sql語句,直接執行查詢sql
示例:
數據庫
測試:
數組
結果:
maven
解釋:咱們能夠在Repository裏自定義方法,可是命名規範是定死的,不是大風颳來的,好比說,方法名的開頭通常以 find | get | read 爲開頭spring-boot
看圖:
測試
具體的命名規範,建議看官方文檔https://docs.spring.io/spring-data/jpa/docs/2.0.7.RELEASE/reference/html/
總結:
自定義一個接口,繼承Repository接口,知足必定命名規範書寫方法名,就能夠不用手寫sql語句,執行查詢操做
3.@Query註解
上面已經說了,繼承Repository接口,便可實現查詢,那麼增刪改查呢中的增刪改呢?
好的,使用@Query註解,能夠實現增、刪、改。
準備:
A. 此時,須要書寫JPQL語句,而且須要用到三個註解@Query、@Modifying、@Transactional
B. 方法分爲有參和無參
(1)以更新操做爲例子
1)這裏先以無參方法爲例,實現一個修改的操做
通常在service層開啓註解
開始測試:
結果:
2)帶參方法,實現一個修改的操做
傳參方式有兩種:命名參數、佔位符
先來第一種:
英文的冒號 ‘ :’ ,後面加上自定義的名字,冒號和名字之間無空格
這裏還漏了一點,使用命名參數傳參,須要在參數中使用@Param註解,裏面的值要和JPQL裏定義參數名的同樣
A. 使用命名參數示例:
service層記住開啓註解
測試:
結果:
注意:
其實還有一點,這一點能夠和接下來的佔位符進行比較,
當有參方法有兩個及以上參數時,好比下面這個,參數的傳遞順序隨意,由於有@Param限定好了
B. 使用佔位符示例:
英文的 '?' ,後面跟着的1啊、2啊或者3456等等,組合起來就表示第一個佔位符,第二個佔位符...
注意:由於使用佔位符,參數傳遞順序嚴格按照JPQL語句中的順序,不能亂,這與使用命名參數傳參的不一樣
因此,我建議使用命名參數傳參,省得錯亂!
(3)若是不熟JPQL語句怎麼辦?用原生sql語句查詢
將上面那個改造一下
nativeQuery = true 即爲使用原生sql
注意:由於是原生sql語句,全部記得表名和字段都要和數據庫字段屬性一一對應起來
(4)爲何會有JPQL語句?爲何還支持原生sql語句?
就用官方事先實現好的,以及知足JPA命名規範的自定義方法去查詢或者更新不行嗎?
還真不行!
好比說,我這有個子查詢,怎麼查?查不了吧。。。
這裏用JPQL或者原生sql就很簡單
(5)like模糊查詢
這裏講講使用@Query的模糊查詢,主要是 '%'的用法,有兩種
1)傳遞參數時,在參數兩邊用%
2)直接寫在@Query裏
推薦使用第二種,傳參就老老實實傳參,別瞎折騰
總結:
1> 記住 @Query、@Modifying、@Transactional、@Param 這四個註解的用處
2> 使用JPQL語句能夠執行查詢、修改、刪除的操做,不能進行增長數據的操做
3> 使用原生sql語句能夠實現增的操做,就是nativeQuery = true(上面忘記說了)
4> 默認狀況下,spring Data 的每一個方法上都有事務,但都是隻讀事務(read-only),是沒法完成修改數據的操做行爲的,因此,如果涉及到對數據進行改動的操做,請開啓事務@Transactional
5> 帶參方法傳參有兩種方式,命名參數、佔位符,我我的推薦命名參數
6> like 模糊查詢傳參也有兩種方式,我的建議直接寫在JPQL語句內更好
4. CrudRepository接口
先點進去,看看,能夠看出官方已經定義好了一些經常使用CRUD的方法
方法都是見名知義啊,就很少作解釋了
舉個例子吧:
以前咱們已經寫好一個findAll的方法,如今我把他給註釋了
而後就報錯了
由於個人返回類型和官方的不同
改改唄:
這種時候,這些簡單CRUD方法,就不用本身寫了,也就是說,本身既能夠不用寫sql,也不用寫自定義方法,用官方提供的現成的就行
總結:自定義一個接口,繼承CrudRepository接口,直接就能夠調用官方提供的一套現成的CRUD方法,美滋滋
5. PagingAndSortingRepository接口
這個也是見名知義的 --分頁、排序用的
點進去,看看
好的,來實現一個分頁排序功能
在這以前,我先把以前的表刪了,從新生成,再造點數據,都是官方提供的deleteAll、save方法啊
如今數據庫中的數據長這樣
(1)分頁
我想把寫好的方法給你們看看,以後再解釋
而後結果:
每頁顯示5條記錄,第三頁,id從16開始,這不扯犢子嗎?id不該該從11開始嗎?
這是第一個問題:page的索引是從0開始的,因此,改一下
結果:
第二個問題:這個id是從11開始了,可是這應該是第三頁啊。
再改
(2)分頁好了,還有排序
總結:PagingAndSortingRepository接口主要就是用來實現分頁排序的
6. JpaRepository接口
老規矩,點進去看看
總結:這個嘛,沒什麼好說的,看方法名就能夠了
7. JpaSpecificationExecutor接口,最後一個
問題:他是用來幹嗎的?
解釋:仍是用來分頁,可是是用他來組合條件分頁
回想一下上面實現的分頁功能,除了傳進去一個起始頁和一個每頁顯示記錄數以及排序條件,還傳了什麼?
沒了,就這三個。夠用嗎,不夠啊。
我想帶個參數模糊查詢不給啊?
我想帶個id比較比較不給啊?
OK!
在上面實現分頁的基礎上,我增長兩個條件,一個是模糊查詢,一個是id比較
先看,以後我再解釋
結果:
解釋一下:
root: 表明查詢的實體類。(這裏即爲Student)
criteriaQuery: 能夠從中可到Root對象,即告知JPA Criteria查詢要查詢哪個實體類, 還能夠來添加查詢條件,還能夠結合EntityManager對象獲得最終查詢的TypedQuery對象。
CriteriaBuilder : 用於建立Criteria 相關對象的工廠。固然能夠從中獲取到Predicate對象
Predicate 類型,表明一個查詢條件。
或者再將上面改改,畢竟參數都是傳遞過來的,不是大風颳來的
其實這樣仍是有問題,思考一下,因爲業務的變動,需求變動,即要判斷的條件可能更多了
這種時候,一開始就用一個數組存放條件不夠優雅,畢竟數組的大小是寫死的
來來來,換成集合走一波
總結:當你想用組合條件分頁查,繼承JpaRepository<T, ID>, JpaSpecificationExecutor<T>唄
綜上,
平常使用,自定義一個接口,繼承JpaRepository接口,
又想組合條件分頁查,繼承JpaSpecificationExecutor接口