图源:
在
模型
假设我们有两张表,学生表和电子邮件账号表,一个学生可以有多个电子邮件账号,一个电子邮件账号只能对应一个学生,这是典型的一对多关系,用数据库模型可以表示为:
实体
用 JPA 实体实现就是:
name = "user_student")
(public class Student {
strategy = GenerationType.IDENTITY)
( private Long id;
max = 45)
( private String name;
private List<Email> emails;
}
name = "user_email")
(public class Email {
strategy = GenerationType.IDENTITY)
( private Long id;
max = 45)
( private String account;
max = 45)
( private String domain;
private Student student;
public String toEmailAddress() {
return "%s@%s".formatted(this.getAccount(), this.getDomain());
}
}
Student
实体有一个emails
属性,表示一个学生可以拥有多个电子邮件。Email
实体有一个student
属性,表示一个电子邮件关联到一个学生。
关联关系
下面为这两个实体创建关联关系:
// ...
public class Student {
// ...
mappedBy = "student",
( fetch = FetchType.EAGER,
cascade = CascadeType.ALL,
orphanRemoval = true)
private List<Email> emails;
// ...
}
// ...
public class Email {
// ...
fetch = FetchType.EAGER)
( name = "student_id")
( private Student student;
// ...
}
方式类似于中介绍的一对一关系的实现,只不过是用@ManyToOne
取代@OneToOne
。想了解相关注解的详细说明的,可以阅读之前的文章。
值得注意的是,就像一对一关系的那样,一对多关系同样存在着“关系拥有者”和“非拥有者”的区别。显然,在一对多关系中,“关系拥有者”必然是一对多关系的“多”所对应的实体(Email
),因为这个实体对应的表(user_email
)才真正拥有指向“一”的主键的外键约束(@JoinColumn(name = "student_id")
)。
因此,在“关系拥有者”这边,我们需要用@JoinColumn
指定外键约束,在关系的另一端(Student
),我们需要用@OneToMany(mappedBy='student')
指定关系由Email.student
属性映射。
其实,“让一条信息能对应多条信息”并不一定要用两张表(实体)来实现,如果不需要对相应的信息进行检索和查询,完全可以在主表上用一个 JSON 格式的字段来保存多条“附加信息”。在 JPA 中可以通过属性转换器来实现,具体的方式可以阅读我的。
The End,谢谢阅读。
可以从获取本文的完整示例代码。
文章评论