java - @ManyToMany 三个表之间的关系

标签 java spring jpa orm

我的 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;

}

关于为多对多关系设置级联类型是棘手的,对于涉及三个表的多对多甚至更棘手,因为每个实体都可以根据情况扮演 parent 或 child 的角色..我建议只坚持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 .但在我看来,如果您像上面那样映射链接表,您会省去很多麻烦。最后是你的电话..

关于java - @ManyToMany 三个表之间的关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42488559/

相关文章:

java - 如何在页面加载时触发 servlet 方法

java - 检查两个非常长的数组是否至少有一个公共(public)元素的最快(运行时)方法?

java - 确定我的应用程序从未安装在设备上以及用户是否正在重新安装的最佳方法是什么?

java - 如何在提交期间捕获 SQLException?

java - Spring AOP : get access to argument names

java - 使用Selenium + Java机器人+剪贴簿下载完整的网页

java - Spring找不到HTTP请求的映射

java - 加速实体管理器3000条记录的提交

java - 如何使用 JPA 编写复杂的连接查询

java - JPA : How to create a self-join entity?