【发布时间】:2017-07-18 05:34:19
【问题描述】:
我的 Spring JPA 应用程序中有三个独立的实体 - 用户、部门、角色
我的数据库中有一个连接表来关联这些实体中的每一个:USER_DEPARTMENT_ROLE
我的问题是,如何在我的实体类中定义这种关系?我是否必须在每个单独的实体中定义 @ManyToMany 关系?我知道如何定义两个表之间的这种关系,但是对于两个以上的表我不知道从哪里开始。
感谢任何帮助!
【问题讨论】:
我的 Spring JPA 应用程序中有三个独立的实体 - 用户、部门、角色
我的数据库中有一个连接表来关联这些实体中的每一个:USER_DEPARTMENT_ROLE
我的问题是,如何在我的实体类中定义这种关系?我是否必须在每个单独的实体中定义 @ManyToMany 关系?我知道如何定义两个表之间的这种关系,但是对于两个以上的表我不知道从哪里开始。
感谢任何帮助!
【问题讨论】:
如果您的联接表中映射了两个以上的关系,那么我建议创建一个单独的实体,用于映射该特定表。
问题是您是否可以有一个不同的 id 列作为人工主键,或者您必须坚持使用由三个外键构建的复合主键。
如果您可以添加人工 id(这是设计数据库的现代方式),那么您的映射应该如下所示:
选项 1
class User {
@OneToMany(mappedBy = "user", cascade = {CascadeType.PERSIST, CascadeType.MERGE})
private Set<UserDepartmentRoleLink> userDepartmentRoleLinks;
}
class Department{
@OneToMany(mappedBy = "department", cascade = {CascadeType.PERSIST, CascadeType.MERGE})
private Set<UserDepartmentRoleLink> userDepartmentRoleLinks;
}
class Role{
@OneToMany(mappedBy = "role", cascade = {CascadeType.PERSIST, CascadeType.MERGE})
private Set<UserDepartmentRoleLink> userDepartmentRoleLinks;
}
class UserDepartmentRoleLink {
@Id
@GeneratedValue
private Long id;
@ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
@JoinColumn(name = "user_id")
private User user;
@ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
@JoinColumn(name = "department_id")
private Department department;
@ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
@JoinColumn(name = "role_id")
private Role role;
}
关于为多对多关系设置级联类型是棘手的,对于涉及三个表的多对多来说甚至更棘手,因为每个实体都可以根据情况扮演父母或孩子的角色。我建议只坚持cascade = {CascadeType.PERSIST, CascadeType.MERGE} 并手动处理其他操作。
如果您必须保留复合主键,那么您应该添加额外的 Id 类并将链接实体更改为以下内容:
选项 2
class User {
@OneToMany(mappedBy = "linkPk.user", cascade = {CascadeType.PERSIST, CascadeType.MERGE})
private Set<UserDepartmentRoleLink> userDepartmentRoleLinks;
}
class Department{
@OneToMany(mappedBy = "linkPk.department", cascade = {CascadeType.PERSIST, CascadeType.MERGE})
private Set<UserDepartmentRoleLink> userDepartmentRoleLinks;
}
class Role{
@OneToMany(mappedBy = "linkPk.role", cascade = {CascadeType.PERSIST, CascadeType.MERGE})
private Set<UserDepartmentRoleLink> userDepartmentRoleLinks;
}
联动表
class UserDepartmentRoleLink {
@EmbeddedId
private UserDepartmentRoleLinkId linkPk
= new UserDepartmentRoleLinkId();
@Transient
public User getUser() {
return getLinkPk().getUser();
}
@Transient
public User getDepartment() {
return getLinkPk().getDepartment();
}
@Transient
public User getRole() {
return getLinkPk().getRole();
}
}
@Embeddable
public class UserDepartmentRoleLinkId implements java.io.Serializable {
@ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
@JoinColumn(name = "user_id")
private User user;
@ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
@JoinColumn(name = "department_id")
private Department department;
@ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
@JoinColumn(name = "role_id")
private Role role;
最重要的是,您可以在此处使用多对多,如本文所述 -> example。但在我看来,如果你像上面那样映射链接表,你会省去很多麻烦。最后,电话是你的..
【讨论】: