本文介绍 Spring Boot 2 使用 JPA 操作数据库的方法。
目录
- JPA 简介
- 开发环境
- 基础示例
JPA 简介
JPA(Java Persistence API)是一种将对象映射到关系数据库的标准技术。Spring Boot 官方的 spring-boot-starter-data-jpa
提供了一下几个关键依赖项。
-
Hibernate
:一种流行的 JPA 实现。 -
Spring Data JPA
:方便实现基于 JPA 的存储库。 -
Spring ORMs
:Spring 框架提供的核心 ORM 支持。
开发环境
- JDK 8
- MySQL 8
基础示例
- 创建存储学生信息的数据表。
CREATE SCHEMA `test` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;
USE `test`;
CREATE TABLE `student` (
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键',
`number` CHAR(10) NOT NULL COMMENT '学号',
`name` VARCHAR(30) NOT NULL COMMENT '姓名',
`gender` TINYINT UNSIGNED NOT NULL COMMENT '性别',
`birth` DATETIME NOT NULL COMMENT '出生日期',
PRIMARY KEY (`id`),
UNIQUE INDEX `id_UNIQUE` (`id` ASC) VISIBLE,
UNIQUE INDEX `number_UNIQUE` (`number` ASC) VISIBLE)
COMMENT = '学生表';
创建 Spring Boot 工程,参考:[IntelliJ IDEA 创建 Spring Boot 工程]。(https://www.jianshu.com/p/8e4092dd96fa)。
在生成的
pom
文件中添加以下依赖:
-
spring-boot-starter-data-jpa
:JPA 依赖 -
mariadb-java-client
:MySQL 数据库驱动
完整 pom
文件内容如下:
4.0.0
org.springframework.boot
spring-boot-starter-parent
2.3.1.RELEASE
tutorial.spring.boot
spring-boot-jpa
1.0.0
spring-boot-jpa
Demo project for Spring Boot JPA
1.8
org.springframework.boot
spring-boot-starter
org.springframework.boot
spring-boot-starter-data-jpa
org.mariadb.jdbc
mariadb-java-client
2.6.1
org.springframework.boot
spring-boot-starter-test
test
org.junit.vintage
junit-vintage-engine
org.apache.commons
commons-lang3
3.10
test
org.springframework.boot
spring-boot-maven-plugin
- 在
application.yml
中添加数据源配置,使用了HikariCP
数据库连接池。
spring:
datasource:
url: jdbc:mysql://localhost:3306/test?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf-8&useSSL=false&allowMultiQueries=true
username: root
password: 123456
driver-class-name: org.mariadb.jdbc.Driver
type: com.zaxxer.hikari.HikariDataSource
hikari:
pool-name: demo-jdbc-pool
minimum-idle: 10
maximum-pool-size: 30
connection-timeout: 60000
idle-timeout: 60000
validation-timeout: 3000
max-lifetime: 600000
- 创建 PO(Persistence Object) 对象
package tutorial.spring.boot.domain;
import javax.persistence.*;
import java.time.LocalDateTime;
@Entity
@Table(name = "student")
public class StudentPO {
/**
* 自增主键
*/
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
/**
* 学号
*/
private String number;
/**
* 姓名
*/
private String name;
/**
* 性别,true-男性,false-女性
*/
private Boolean gender;
/**
* 出生日期
*/
private LocalDateTime birth;
// Getter、Setter、toString 方法略
}
- 创建一个继承
JpaRepository
的 Repository 接口类。
package tutorial.spring.boot.dao;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import tutorial.spring.boot.domain.StudentPO;
@Repository
public interface StudentRepository extends JpaRepository {
}
- 至此便可直接使用
StudentRepository
完成student
表的数据操作,以下是一个简单测试 JPA 功能的单元测试用例,执行结果略。
package tutorial.spring.boot.dao;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.RandomUtils;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.RepeatedTest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import tutorial.spring.boot.domain.StudentPO;
import java.time.LocalDateTime;
import java.util.Optional;
@SpringBootTest
class StudentRepositoryTest {
@Autowired
private StudentRepository studentRepository;
@RepeatedTest(10)
void test() {
Assertions.assertThat(studentRepository).isNotNull();
Assertions.assertThat(studentRepository.count()).isEqualTo(0);
StudentPO student = new StudentPO();
student.setNumber(RandomStringUtils.randomAlphanumeric(10));
student.setName(RandomStringUtils.randomAlphanumeric(2, 20));
student.setGender(RandomUtils.nextBoolean());
student.setBirth(LocalDateTime.of(RandomUtils.nextInt(2000, 2010),
RandomUtils.nextInt(1, 13),
RandomUtils.nextInt(1, 28),
RandomUtils.nextInt(0, 24),
RandomUtils.nextInt(0, 60),
RandomUtils.nextInt(0, 60)));
StudentPO saveResult = studentRepository.save(student);
Assertions.assertThat(saveResult.getId()).isNotNull();
Assertions.assertThat(studentRepository.count()).isEqualTo(1);
Optional findResult = studentRepository.findById(saveResult.getId());
Assertions.assertThat(findResult).isPresent();
Assertions.assertThat(findResult.get().getNumber()).isEqualTo(student.getNumber());
Assertions.assertThat(findResult.get().getName()).isEqualTo(student.getName());
Assertions.assertThat(findResult.get().getGender()).isEqualTo(student.getGender());
Assertions.assertThat(findResult.get().getBirth()).isEqualTo(student.getBirth());
studentRepository.delete(student);
Assertions.assertThat(studentRepository.count()).isEqualTo(0);
}
}