芋道 Spring Boot JPA 入門(一)之快速入門
- 2019 年 11 月 29 日
- 筆記
摘要: 原創出處 http://www.iocoder.cn/Spring-Boot/JPA/ 「芋道源碼」歡迎轉載,保留摘要,謝謝!
- 1. 概述
- 2. 快速入門
- 3. 分頁操作
- 4. 基於方法名查詢
- 5. 基於註解查詢
- 666. 彩蛋
本文,我們基於 Spring Boot 2.X 版本。
1. 概述
我們,咱們來學習下 Spring Data JPA 。
相信不少胖友之前有了解過 JPA、Hibernate ,那麼 JPA、Hibernate、Spring Data JPA 這三者是什麼關係呢?我們來一起理一理。
JPA ,全稱 Java Persistence API ,是由 Java 定義的 Java ORM 以及實體操作 API 的標準。正如最早學習 JDBC 規範,Java 自身並未提供相關的實現,而是 MySQL 提供 MySQL mysql-connector-java 驅動,Oracle 提供 oracle-jdbc 驅動。而實現 JPA 規範的有:
- Hibernate ORM
- Oracle TopLink
- Apache OpenJPA
Spring Data JPA ,是 Spring Data 提供的一套簡化的 JPA 開發的框架。
- 內置 CRUD、分頁、排序等功能的操作。
- 根據約定好的方法名規則,自動生成對應的查詢操作。
- 使用
@Query
註解,自定義 SQL 。
所以,絕大多數情況下,我們無需編寫程式碼,直接調用 JPA 的 API 。也因此,在我們使用的 Spring Data JPA 的項目中,如果想要替換底層使用的 JPA 實現框架,在未使用到相關 JPA 實現框架的特殊特性的情況下,可以透明替換。
關於這一點,我們在 《芋道 Spring Boot Redis 入門》 中,已經看到 Spring Data Redis 也是已經看到這樣的好處。
總的來說,就是如下一張圖:
FROM 《spring data jpa hibernate jpa 三者之間的關係》

當然,絕大多數情況下,我們使用的 JPA 實現框架是 Hibernate ORM 。所以整個調用過程是:
應用程式 => Repository => Spring Data JPA => Hibernate
2. 快速入門
示例程式碼對應倉庫:lab-13-jpa 。
本小節,我們會使用 spring-boot-starter-data-jpa
自動化配置 Spring Data JPA 。同時,演示 Spring Data JPA 的 CRUD 的操作。
2.1 引入依賴
在 pom.xml
文件中,引入相關依賴。
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.3.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>lab-13-jpa</artifactId> <dependencies> <!-- 實現對資料庫連接池的自動化配置 --> <!-- 實際上 spring-boot-starter-data-jpa 已經包括 spring-boot-starter-jdbc --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <dependency> <!-- 本示例,我們使用 MySQL --> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.48</version> </dependency> <!-- 實現對 Spring Data JPA 的自動化配置 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <!-- 方便等會寫單元測試 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> </project>
具體每個依賴的作用,胖友自己認真看下艿艿添加的所有注釋噢。
另外,在 spring-boot-starter-data-jpa
中,已經默認引入了 Hibernate 的依賴。
2.2 Application
創建 Application.java
類,配置 @SpringBootApplication
註解即可。程式碼如下:
// Application.java @SpringBootApplication public class Application { }
2.3 配置文件
在 application.yml
中,添加 JPA 配置,如下:
spring: # datasource 數據源配置內容 datasource: url: jdbc:mysql://47.112.193.81:3306/testb5f4?useSSL=false&useUnicode=true&characterEncoding=UTF-8 driver-class-name: com.mysql.jdbc.Driver username: testb5f4 password: F4df4db0ed86@11 # JPA 配置內容,對應 JpaProperties 類 jpa: show-sql: true # 列印 SQL 。生產環境,建議關閉 # Hibernate 配置內容,對應 HibernateProperties 類 hibernate: ddl-auto: none
datasource
配置項,配置 datasource 數據源配置內容。jpa
配置項,配置 Spring Data JPA 配置內容,對應 `org.springframework.boot.autoconfigure.orm.jpa.JpaProperties.java` 類。hibernate
配置項,配置 Hibernate 配置內容,對應org.springframework.boot.autoconfigure.orm.jpa.HibernateProperties.java
類。- create :每次載入 hibernate 時都會刪除上一次的生成的表,然後根據你的 model 類再重新來生成新表,哪怕兩次沒有任何改變也要這樣執行,這就是導致資料庫表數據丟失的一個重要原因。
- create-drop :每次載入 hibernate 時根據 model 類生成表,但是 sessionFactory 一關閉,表就自動刪除。
- update :最常用的屬性,第一次載入 hibernate 時根據 model 類會自動建立起表的結構(前提是先建立好資料庫),以後載入 hibernate 時根據 model 類自動更新表結構,即使表結構改變了但表中的行仍然存在不會刪除以前的行。要注意的是當部署到伺服器後,表結構是不會被馬上建立起來的,是要等應用第一次運行起來後才會。
- validate :每次載入 hibernate 時,驗證創建資料庫表結構,只會和資料庫中的表進行比較,不會創建新表,但是會插入新值。
- 建議,生產環境下,建議配置
none
,不使用 Hibernate Auto DDL 功能。? 啟動個項目,就自動變更資料庫表結構,多危險啊~ - 實際項目無需配置
hibernate
配置項,這裡僅僅是演示,讓胖友知道這回事。 ddl-auto
配置項,設置 Hibernate DDL 處理策略。一共有none
、create
、create-drop
、update
、validate
五個選項。 FROM 《jpa 的 hibernate.ddl-auto 的幾個屬性值區別》
2.4 UserDO
在 cn.iocoder.springboot.lab13.jpa.dataobject
包路徑下,創建 UserDO.java 類,用戶 DO 。程式碼如下:
// UserDO.java @Entity @Table(name = "users") public class UserDO { /** * 用戶編號 */ @Id @GeneratedValue(strategy = GenerationType.IDENTITY, // strategy 設置使用資料庫主鍵自增策略; generator = "JDBC") // generator 設置插入完成後,查詢最後生成的 ID 填充到該屬性中。 private Integer id; /** * 帳號 */ @Column(nullable = false) private String username; /** * 密碼(明文) * * ps:生產環境下,千萬不要明文噢 */ @Column(nullable = false) private String password; /** * 創建時間 */ @Column(name = "create_time", nullable = false) private Date createTime; // ... 省略 setting/getting 方法 }
關於 JPA 的註解的詳細說明,胖友後面再看看 《Spring Data JPA 中常用的註解詳解》 文章。我們,繼續往下看。
對應的創建表的 SQL 如下:
CREATE TABLE `users` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '用戶編號', `username` varchar(64) COLLATE utf8mb4_bin DEFAULT NULL COMMENT '帳號', `password` varchar(32) COLLATE utf8mb4_bin DEFAULT NULL COMMENT '密碼', `create_time` datetime DEFAULT NULL COMMENT '創建時間', PRIMARY KEY (`id`), UNIQUE KEY `idx_username` (`username`) ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;
2.5 UserRepository01
在 cn.iocoder.springboot.lab13.mybatis.repository
包路徑下,創建 UserRepository01 介面。程式碼如下:
// UserRepository01.java public interface UserRepository01 extends CrudRepository<UserDO, Integer> { }
- 繼承
org.springframework.data.repository.CrudRepository
介面,第一個泛型設置對應的實體是 UserDO ,第二個泛型設置對應的主鍵類型是 Integer 。 - 因為實現了 CrudRepository 介面,Spring Data JPA 會自動生成對應的 CRUD 的程式碼。具體 CrudRepository 提供了哪些操作,胖友點擊 `CrudRepository.java` 查看。
2.6 簡單測試
創建 UserRepository01Test 測試類,我們來測試一下簡單的 UserRepository01 的每個操作。程式碼如下:
// UserRepository01.java @RunWith(SpringRunner.class) @SpringBootTest(classes = Application.class) public class UserMapperTest { @Autowired private UserMapper userMapper; @Test public void testInsert() { UserDO user = new UserDO().setUsername(UUID.randomUUID().toString()) .setPassword("nicai").setCreateTime(new Date()); userMapper.insert(user); } @Test public void testUpdateById() { UserDO updateUser = new UserDO().setId(1) .setPassword("wobucai"); userMapper.updateById(updateUser); } @Test public void testDeleteById() { userMapper.deleteById(2); } @Test public void testSelectById() { userMapper.selectById(1); } @Test public void testSelectByUsername() { userMapper.selectByUsername("yunai"); } @Test public void testSelectByIds() { List<UserDO> users = userMapper.selectByIds(Arrays.asList(1, 3)); System.out.println("users:" + users.size()); } }
具體的,胖友可以自己跑跑,妥妥的。
3. 分頁操作
示例程式碼對應倉庫:lab-13-jpa 。
Spring Data 提供 org.springframework.data.repository.PagingAndSortingRepository
介面,繼承 CrudRepository 介面,在 CRUD 操作的基礎上,額外提供分頁和排序的操作。程式碼如下:
// PagingAndSortingRepository.java public interface PagingAndSortingRepository<T, ID> extends CrudRepository<T, ID> { Iterable<T> findAll(Sort sort); // 排序操作 Page<T> findAll(Pageable pageable); // 分頁操作 }
3.1 UserRepository02
在 cn.iocoder.springboot.lab13.mybatis.repository
包路徑下,創建 UserRepository02 介面。程式碼如下:
// UserRepository02.java public interface UserRepository02 extends PagingAndSortingRepository<UserDO, Integer> { }
- 實現 PagingAndSortingRepository 介面,第一個泛型設置對應的實體是 UserDO ,第二個泛型設置對應的主鍵類型是 Integer 。
3.2 簡單測試
創建 UserRepository02Test 測試類,我們來測試一下簡單的 UserRepository02 的每個操作。程式碼如下:
// UserRepository02Test.java @RunWith(SpringRunner.class) @SpringBootTest public class UserRepository02Test { @Autowired private UserRepository02 userRepository; @Test // 排序 public void testFindAll() { // 創建排序條件 Sort sort = new Sort(Sort.Direction.DESC, "id"); // 執行排序操作 Iterable<UserDO> iterable = userRepository.findAll(sort); // 列印 iterable.forEach(System.out::println); } @Test // 分頁 public void testFindPage() { // 創建排序條件 Sort sort = new Sort(Sort.Direction.DESC, "id"); // 創建分頁條件 Pageable pageable = PageRequest.of(1, 10, sort); // 執行分頁操作 Page<UserDO> page = userRepository.findAll(pageable); // 列印 System.out.println(page.getTotalElements()); System.out.println(page.getTotalPages()); } }
具體的,胖友可以自己跑跑,妥妥的。