120 lines
4.3 KiB
Markdown
120 lines
4.3 KiB
Markdown
|
Java Persistence API (JPA) 提供了一套丰富的机制来处理实体之间的关联关系,这些关联关系是面向对象模型中的核心部分,也是数据库设计的关键。JPA主要支持以下几种关联关系类型:
|
|||
|
|
|||
|
### 1. 一对一(One-to-One)
|
|||
|
- **定义**:两个实体之间存在一对一的关联关系,即一个实体最多只能与另一个实体的一个实例关联。
|
|||
|
- **映射**:使用`@OneToOne`和`@JoinColumn`注解来定义,通常在“拥有”关联的一方放置`@JoinColumn`指定外键列。
|
|||
|
- **双向**:需要在另一方添加`mappedBy`属性指定关系的拥有方。
|
|||
|
|
|||
|
例如,一个用户(User)可以有一个个人资料(Profile),而每个个人资料只属于一个用户。
|
|||
|
|
|||
|
```java
|
|||
|
@Entity
|
|||
|
public class User {
|
|||
|
@Id
|
|||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
|||
|
private Long id;
|
|||
|
|
|||
|
@OneToOne(mappedBy = "user", cascade = CascadeType.ALL)
|
|||
|
private Profile profile;
|
|||
|
|
|||
|
// Getters and Setters
|
|||
|
}
|
|||
|
|
|||
|
@Entity
|
|||
|
public class Profile {
|
|||
|
@Id
|
|||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
|||
|
private Long id;
|
|||
|
|
|||
|
@OneToOne
|
|||
|
@JoinColumn(name = "user_id", unique = true)
|
|||
|
private User user;
|
|||
|
|
|||
|
// Getters and Setters
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
### 2. 一对多(One-to-Many)
|
|||
|
- **定义**:一个实体可以与多个其他实体实例关联。
|
|||
|
- **映射**:`@OneToMany`与`@JoinColumn`(或`@JoinTable`),通常放在“一”方,而“多”方通常使用`mappedBy`指定关系的来源。
|
|||
|
- **双向**:如果需要双向关联,一方使用`mappedBy`指定对方为关联的拥有方。
|
|||
|
|
|||
|
例如,一个部门(Department)可以有多个员工(Employee),但每个员工只属于一个部门。
|
|||
|
|
|||
|
```java
|
|||
|
@Entity
|
|||
|
public class Department {
|
|||
|
@Id
|
|||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
|||
|
private Long id;
|
|||
|
|
|||
|
@OneToMany(mappedBy = "department", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
|
|||
|
private List<Employee> employees;
|
|||
|
|
|||
|
// Getters and Setters
|
|||
|
}
|
|||
|
|
|||
|
@Entity
|
|||
|
public class Employee {
|
|||
|
@Id
|
|||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
|||
|
private Long id;
|
|||
|
|
|||
|
@ManyToOne
|
|||
|
@JoinColumn(name = "department_id")
|
|||
|
private Department department;
|
|||
|
|
|||
|
// Getters and Setters
|
|||
|
}
|
|||
|
```
|
|||
|
### 3. 多对一(Many-to-One)
|
|||
|
- **实质**:多对一关系是“一对多”关系的反向查看,逻辑上相同,只是映射侧重点不同。
|
|||
|
- **映射**:使用`@ManyToOne`和`@JoinColumn`,通常在“多”方定义外键列。
|
|||
|
|
|||
|
在上面的一对多示例中,从 Employee 到 Department 的关联就是多对一关系。
|
|||
|
|
|||
|
### 4. 多对多(Many-to-Many)
|
|||
|
- **定义**:两个实体集之间存在多对多的关联。
|
|||
|
- **映射**:使用`@ManyToMany`结合`@JoinTable`来定义中间关联表,这个表存储两个实体的外键。
|
|||
|
- **双向**:双方都可以维护关联,通常需要在一方或双方设置`mappedBy`。
|
|||
|
|
|||
|
例如,一个学生(Student)可以选修多门课程(Course),而每门课程也可以被多个学生选修。
|
|||
|
|
|||
|
```java
|
|||
|
@Entity
|
|||
|
public class Student {
|
|||
|
@Id
|
|||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
|||
|
private Long id;
|
|||
|
|
|||
|
@ManyToMany(mappedBy = "students")
|
|||
|
private Set<Course> courses = new HashSet<>();
|
|||
|
|
|||
|
// Getters and Setters
|
|||
|
}
|
|||
|
|
|||
|
@Entity
|
|||
|
public class Course {
|
|||
|
@Id
|
|||
|
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
|||
|
private Long id;
|
|||
|
|
|||
|
@ManyToMany
|
|||
|
@JoinTable(
|
|||
|
name = "student_course",
|
|||
|
joinColumns = @JoinColumn(name = "course_id"),
|
|||
|
inverseJoinColumns = @JoinColumn(name = "student_id")
|
|||
|
)
|
|||
|
private Set<Student> students = new HashSet<>();
|
|||
|
|
|||
|
// Getters and Setters
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
### 处理关联的注意事项:
|
|||
|
- **懒加载与急加载**:通过`fetch=FetchType.LAZY`或`FetchType.EAGER`控制关联关系的加载方式。
|
|||
|
- **级联操作**:使用`cascade=CascadeType`属性定义操作如何影响关联的对象,如保存、删除等。
|
|||
|
- **双向关联维护**:确定哪一方负责维护关联关系,通常外键所在方维护关联。
|
|||
|
- **孤儿移除策略**:考虑关联对象被删除时的处理方式,是否级联删除或设置为null。
|
|||
|
|
|||
|
JPA通过这些机制,使得开发者能够以面向对象的方式处理复杂的数据库关系,同时保持了数据库的规范性和数据的一致性。正确地设计和管理实体关联是构建高效、可维护的JPA应用程序的关键。
|