JPA 实体关系映射:@ManyToMany 多对多关系、@OneToMany @ManyToOne 一对多多对一关系和 @OneToOne 的实例解析。

JPA 中的实体关系映射可以极大程度的减少开发的工作量,把冗余的操作交给底层框架完成。相较 MyBatis 来说,简单的增删改查要方便简单许多,也更加的快捷和便携。在 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
33
34
35
Student 类
Entity
@NoArgsConstructor
@Getter
@Setter
public class Student {

@Id
@GeneratedValue(generator = "idGenerator")
@GenericGenerator(name = "idGenerator", strategy = "uuid")
private String id;

private String studentName;

@ManyToMany(cascade=CascadeType.ALL,fetch=FetchType.LAZY)
private Set<Course> courses = new HashSet<>();
}

Course 类

@Entity
@NoArgsConstructor
@Getter
@Setter
public class Course {
@Id
@GeneratedValue(generator = "idGenerator")
@GenericGenerator(name = "idGenerator", strategy = "uuid")
private String id;

private String courseName;

@ManyToMany(cascade=CascadeType.ALL,fetch=FetchType.LAZY,mappedBy="courses")
private Set<Student> students= new HashSet<>();
}

@ManyToMany 这一注解表明,当前实体为多对多关系的其中一端。注解可以在Collection、Set、List、Map上使用,我们可以根据业务需要选择。并且我们可以根据业务逻辑的不同的需求给与不同的实现,比如可以使用 ArrayList、TreeMap 等。

在注解中,我们可以设置cascade(级联关系),fetch(加载策略),mappedBy(声明关系的维护方)等属性。

mappedBy 声明于关系的 被维护方,声明的值为关系的维护方的关系对象属性名。
在实例中,mappedBy 被声明于 Course 类中,其值为 Student 类中的 courses。即 Student 为关系维护方,Course 为被维护方。

一对多、多对一与一对一关系映射

一对多关系即数据库中的一行数据关联另一个数据库中的多行关系。多对一与之相反。
一对多与多对一关系也可能会有中间表关联两者。但是我们一般不建议使用中间表。使用mapperBy可以避免系统生成中间表(会在多的一方数据库中增加一个字段记录外键)。
这两个关系中的mappedBy一般声明于一的一方,即一的一方为被维护方。

1
2
3
4
5
6
7
8
9
10
public class Student {
@ManyToOne(cascade=CascadeType.ALL,fetch=FetchType.LAZY)
private ClassEntity classEntity;
//其余略
}
public class ClassEntity {
@OneToMany(cascade=CascadeType.PERSIST,fetch=FetchType.LAZY,mappedBy="classEntity")
private Set<Student> students= new HashSet<>();
//其余略
}

一对一关系即两个数据库中的数据一一对应。

1
2
3
4
5
6
7
8
9
public class NewsResourceEntity{
@OneToOne(optional = false, cascade = CascadeType.MERGE)
private ResourceEntity resource;
//其余略
}
public class ResourceEntity {
@OneToOne(optional = true, cascade = CascadeType.ALL, fetch=FetchType.LAZY, mappedBy = "resource")
private NewsResourceEntity newsResource;
}

当使用单向关联时,由父类管理关联关系,子类无法管理,而这时,父亲知道自己的儿子,但是,从儿子对象不知道父亲是谁。
单向关联时,只指定
当使用双向关联时,关联关系的管理可以通过inverse指定,这时,儿子能清楚的知道自己的父亲是谁。 双向关联时,还要指定

参考链接:https://www.jianshu.com/p/54108abb070f