JPA 概述

JPA(Java Persistence API)是 Java EE/ Jakarta EE 的官方 ORM 规范,提供了一套标准 API 实现以下功能:

  • 对象关系映射(ORM)
  • 实体生命周期管理
  • JPQL 查询语言
  • 事务控制
  • 二级缓存支持

這裡支隊 JPA 做一個大概的介紹,因為使用目前主流的 mybatis 或者 hibernate 就可以了

使用

第一步,引入依賴並配置

JPA 实体类定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
@Entity
@Table(name = "users")
public class User {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Column(name = "username", nullable = false, length = 50)
private String username;

@Column(name = "email", unique = true)
private String email;

@Enumerated(EnumType.STRING)
@Column(name = "role")
private Role role;

@Temporal(TemporalType.TIMESTAMP)
@Column(name = "created_at")
private Date createdAt;

@OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
private List<Order> orders = new ArrayList<>();

// 构造方法、getter、setter 等
}

public enum Role {
ADMIN, USER, GUEST
}

实体关系映射

  • 一对一关系
  • 一对多
  • 多对多关系

事务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
public class JpaDemo {
public static void main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("jpa-demo");
EntityManager em = emf.createEntityManager();

try {
// 开始事务
em.getTransaction().begin();

// 创建新用户
User user = new User();
user.setUsername("johndoe");
user.setEmail("john@example.com");
user.setRole(Role.USER);
user.setCreatedAt(new Date());

// 持久化实体
em.persist(user);

// 提交事务
em.getTransaction().commit();

// 查询用户
User foundUser = em.find(User.class, user.getId());
System.out.println("Found user: " + foundUser.getUsername());

// JPQL 查询
TypedQuery<User> query = em.createQuery(
"SELECT u FROM User u WHERE u.role = :role", User.class);
query.setParameter("role", Role.USER);
List<User> users = query.getResultList();

// 更新用户
em.getTransaction().begin();
foundUser.setEmail("new-email@example.com");
em.getTransaction().commit();

// 删除用户
em.getTransaction().begin();
em.remove(foundUser);
em.getTransaction().commit();

} finally {
em.close();
emf.close();
}
}
}

Spring JPA

引入依賴

1
2
3
4
5
6
7
8
9
10
11
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-bom</artifactId>
<version>2023.0.0-SNAPSHOT</version>
<scope>import</scope>
<type>pom</type>
</dependency>
</dependencies>
</dependencyManagement>

定义 Repository 接口

要定义一个 repository 接口,你首先需要定义一个 domain 类专用的 repository 接口。该接口必须继承 Repository,并将其泛型设置为 domain 类和 ID 类。
示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
@NoRepositoryBean
interface MyBaseRepository<T, ID> extends Repository<T, ID> {

Optional<T> findById(ID id);

<S extends T> S save(S entity);
}

interface UserRepository extends MyBaseRepository<User, Long> {
User findByEmailAddress(EmailAddress emailAddress);
}


在数据模块中使用 Repository

1
2
3
4
5
6
7
interface MyRepository extends JpaRepository<User, Long> { }

@NoRepositoryBean
interface MyBaseRepository<T, ID> extends JpaRepository<T, ID> { … }

interface UserRepository extends MyBaseRepository<User, Long> { … }

MyRepository 和 UserRepository 在其类型层次上扩展了 JpaRepository。它们是 Spring Data JPA 模块的有效候选者。

帶註解

1
2
3
4
5
6
7
8
9
10
interface PersonRepository extends Repository<Person, Long> { … }

@Entity
class Person { … }

interface UserRepository extends Repository<User, Long> { … }

@Document
class User { … }

PersonRepository 引用了 Person,它被 JPA 的 @Entity 注解所注解,所以这个 repository 显然属于 Spring Data JPA。UserRepository 引用了 User,它被 Spring Data MongoDB 的 @Document 注解所注解。

查詢

具體如何實現請不在本文講述範圍內,因為博主平時只使用的是 mybatis,JPA 只做了解。若感興趣,請自行查閱

高級特性

二级缓存

批量处理

乐观锁