點選上方“芋道原始碼”,選擇“置頂公眾號”
技術文章第一時間送達!
原始碼精品專欄
摘要: 原文可閱讀 http://www.iocoder.cn/Spring-Boot/battcn/v2-orm-jpa/ 「唐亞峰」歡迎轉載,保留摘要,謝謝!
-
JPA
-
Spring Data JPA
-
匯入依賴
-
連線資料庫
-
JPA配置
-
輸出日誌
-
資料庫型別
-
具體編碼
-
物體類
-
Repository
-
測試
-
總結
-
說點什麼
SpringBoot
是為了簡化Spring
應用的建立、執行、除錯、部署等一系列問題而誕生的產物,自動裝配的特性讓我們可以更好的關註業務本身而不是外部的XML配置,我們只需遵循規範,引入相關的依賴就可以輕易的搭建出一個 WEB 工程
上一篇介紹了Spring JdbcTemplate
的使用,對比原始的JDBC
而言,它更加的簡潔。但隨著表的增加,重覆的CRUD工作讓我們苦不堪言,這時候Spring Data Jpa
的作用就體現出來了…..
JPA
JPA是Java Persistence API
的簡稱,中文名Java持久層API,是官方(Sun)在JDK5.0後提出的Java持久化規範。其目的是為了簡化現有JAVA EE
和JAVA SE
應用開發工作,以及整合現有的ORM技術實現規範統一
JPA的總體思想和現有
Hibernate
、TopLink
、JDO
等ORM框架大體一致。總的來說,JPA包括以下3方面的技術:
-
ORM對映元資料: 支援XML和註解兩種元資料的形式,元資料描述物件和表之間的對映關係,框架據此將物體物件持久化到資料庫表中;
-
API: 操作物體物件來執行CRUD操作,框架在後臺替代我們完成所有的事情,開發者從繁瑣的JDBC和SQL程式碼中解脫出來。
-
查詢語言: 透過面向物件而非面向資料庫的查詢語言查詢資料,避免程式的SQL陳述句緊密耦合。
JPA只是一種規範,它需要第三方自行實現其功能,在眾多框架中Hibernate
是最為強大的一個。從功能上來說,JPA就是Hibernate功能的一個子集。Hibernate 從3.2開始,就開始相容JPA。同時Hibernate3.2獲得了Sun TCK的JPA(Java Persistence API) 相容認證。
Spring Data JPA
常見的ORM框架中Hibernate
的JPA最為完整,因此Spring Data JPA
是採用基於JPA規範的Hibernate
框架基礎下提供了Repository
層的實現。Spring Data Repository極大地簡化了實現各種持久層的資料庫訪問而寫的樣板程式碼量,同時CrudRepository提供了豐富的CRUD功能去管理物體類。
優點
-
豐富的API,簡單操作無需編寫額外的程式碼
-
豐富的SQL日誌輸出
缺點
-
學習成本較大,需要學習HQL
-
配置複雜,雖然
SpringBoot
簡化的大量的配置,關係對映多表查詢配置依舊不容易 -
效能較差,對比
JdbcTemplate
、Mybatis
等ORM框架,它的效能無異於是最差的
匯入依賴
在 pom.xml
中新增 spring-boot-starter-data-jpa
的依賴
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-data-jpaartifactId>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
連線資料庫
在application.properties
中新增如下配置。值得註意的是,SpringBoot預設會自動配置DataSource
,它將優先採用HikariCP
連線池,如果沒有該依賴的情況則選取tomcat-jdbc
,如果前兩者都不可用最後選取Commons DBCP2
。透過spring.datasource.type屬性可以指定其它種類的連線池
spring.datasource.url=jdbc:mysql://localhost:3306/chapter5?useUnicode=true&characterEncoding;=UTF-8&zeroDateTimeBehavior;=convertToNull&allowMultiQueries;=true&useSSL;=false
spring.datasource.password=root
spring.datasource.username=root
#spring.datasource.type
# JPA配置
spring.jpa.hibernate.ddl-auto=update
# 輸出日誌
spring.jpa.show-sql=true
# 資料庫型別
spring.jpa.database=mysql
ddl-auto 幾種屬性
-
create: 每次執行程式時,都會重新建立表,故而資料會丟失
-
create-drop: 每次執行程式時會先建立表結構,然後待程式結束時清空表
-
upadte: 每次執行程式,沒有表時會建立表,如果物件發生改變會更新表結構,原有資料不會清空,只會更新(推薦使用)
-
validate: 執行程式會校驗資料與資料庫的欄位型別是否相同,欄位不同會報錯
具體編碼
由於上面我們採用的是spring.jpa.hibernate.ddl-auto=update
方式,因此這裡可以跳過手動建表的操作
物體類
JPA規範註解坐落在javax.persistence
包下,@Id註解一定不要取用錯了,否則會報錯。@GeneratedValue(strategy = GenerationType.IDENTITY)自增策略,不需要對映的欄位可以透過@Transient註解排除掉
常見的幾種自增策略
-
TABLE: 使用一個特定的資料庫表格來儲存主鍵
-
SEQUENCE: 根據底層資料庫的序列來生成主鍵,條件是資料庫支援序列。這個值要與generator一起使用,generator 指定生成主鍵使用的生成器(可能是orcale中自己編寫的序列)。
-
IDENTITY: 主鍵由資料庫自動生成(主要是支援自動增長的資料庫,如mysql)
-
AUTO: 主鍵由程式控制,也是GenerationType的預設值。
package com.battcn.entity;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import java.io.Serializable;
/**
* @author Levin
* @since 2018/5/7 0007
*/
@Entity(name = "t_user")
public class User implements Serializable {
private static final long serialVersionUID = 8655851615465363473L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String username;
private String password;
/**
* TODO 忽略該欄位的對映
*/
@Transient
private String email;
// TODO 省略get set
}
Repository
建立UserRepository
資料訪問層介面,需要繼承JpaRepository
,第一個泛型引數是物體物件的名稱,第二個是主鍵型別。只需要這樣簡單的配置,該UserRepository
就擁常用的CRUD
功能,JpaRepository
本身就包含了常用功能,剩下的查詢我們按照規範寫介面即可,JPA支援@Query註解寫HQL,也支援findAllByUsername這種根據欄位名命名的方式(強烈推薦IntelliJ IDEA對JPA支援非常NICE)
package com.battcn.repository;
import com.battcn.entity.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
/**
* t_user 操作
*
* @author Levin
* @since 2018/5/7 0007
*/
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
/**
* 根據使用者名稱查詢使用者資訊
*
* @param username 使用者名稱
* @return 查詢結果
*/
List findAllByUsername(String username) ;
}
測試
完成資料訪問層介面後,最後編寫一個junit
測試類來檢驗程式碼的正確性。
下麵的幾個操作中,只有findAllByUsername
是我們自己編寫的程式碼,其它的都是繼承自JpaRepository
介面中的方法,更關鍵的是分頁及排序是如此的簡單實體化一個Pageable
即可…
package com.battcn;
import com.battcn.entity.User;
import com.battcn.repository.UserRepository;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.List;
/**
* @author Levin
*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class Chapter5ApplicationTests {
private static final Logger log = LoggerFactory.getLogger(Chapter5ApplicationTests.class);
@Autowired
private UserRepository userRepository;
@Test
public void test1() throws Exception {
final User user = userRepository.save(new User("u1", "p1"));
log.info("[新增成功] - [{}]", user);
final List u1 = userRepository.findAllByUsername("u1");
log.info("[條件查詢] - [{}]", u1);
Pageable pageable = PageRequest.of(0, 10, Sort.by(Sort.Order.desc("username")));
final Page users = userRepository.findAll(pageable);
log.info("[分頁+排序+查詢所有] - [{}]", users.getContent());
userRepository.findById(users.getContent().get(0).getId()).ifPresent(user1 -> log.info("[主鍵查詢] - [{}]", user1));
final User edit = userRepository.save(new User(user.getId(), "修改後的ui", "修改後的p1"));
log.info("[修改成功] - [{}]", edit);
userRepository.deleteById(user.getId());
log.info("[刪除主鍵為 {} 成功] - [{}]", user.getId());
}
}
總結
更多內容請參考官方檔案
目前很多大佬都寫過關於 SpringBoot 的教程了,如有雷同,請多多包涵,本教程基於最新的 spring-boot-starter-parent:2.0.1.RELEASE
編寫,包括新版本的特性都會一起介紹…
說點什麼
全文程式碼:https://github.com/battcn/spring-boot2-learning/tree/master/chapter5
666. 彩蛋
如果你對 Dubbo 感興趣,歡迎加入我的知識星球一起交流。
目前在知識星球(https://t.zsxq.com/2VbiaEu)更新瞭如下 Dubbo 原始碼解析如下:
01. 除錯環境搭建
02. 專案結構一覽
03. 配置 Configuration
04. 核心流程一覽
05. 拓展機制 SPI
06. 執行緒池
07. 服務暴露 Export
08. 服務取用 Refer
09. 註冊中心 Registry
10. 動態編譯 Compile
11. 動態代理 Proxy
12. 服務呼叫 Invoke
13. 呼叫特性
14. 過濾器 Filter
15. NIO 伺服器
16. P2P 伺服器
17. HTTP 伺服器
18. 序列化 Serialization
19. 叢集容錯 Cluster
20. 優雅停機
21. 日誌適配
22. 狀態檢查
23. 監控中心 Monitor
24. 管理中心 Admin
25. 運維命令 QOS
26. 鏈路追蹤 Tracing
…
一共 60 篇++