【问题标题】:Hibernate annotations: Many-to-many with shared composite key attributeHibernate 注释:具有共享复合键属性的多对多
【发布时间】:2020-03-04 21:04:46
【问题描述】:

我正在尝试使用 Hibernate+JPA 注释映射现有的数据库架构。

我的一个实体的映射如下:

@Entity
@Table(name = "users")
public class User implements Serializable {

    @Id
    private int department;

    @Id
    private int userId;

    ...

还有另一个实体,组:

@Entity
@Table(name = "groups")
public class Group implements Serializable {

    @Id
    private int department;

    @Id
    private int groupId;

    ...

Group 和 User 之间应该有多对多的关系,但问题是连接表(“user_group”)只有“DEPARTMENT, USERID, GROUPID”列 - 即需要使用 DEPARTMENT 列在 joinColumns 和 inverseJoinColumns 中:

    @ManyToMany(cascade = { CascadeType.ALL })
    @JoinTable(
        name = "user_groups",
        joinColumns = { @JoinColumn(name = "department"), @JoinColumn(name = "groupid") },
        inverseJoinColumns = {@JoinColumn(name = "department"), @JoinColumn(name = "userid") }
    )
    private List<User> groupUsers = new ArrayList<>();

这会导致映射错误 - “实体映射中的重复列”。

但是,使用 XML 看起来这是/可能的,因为这个确切的例子存在于 old Hibernate documentation. 但我找不到任何证据表明这曾经使用注释有效?我尝试使用@JoinFormula 而不是@JoinColumn,但这无法编译。有可能吗?

【问题讨论】:

    标签: java hibernate


    【解决方案1】:

    好的,我很确定这是不可能的。

    我找到了一个有希望的解决方法:

    为“user_group”表创建一个@Embeddable:

    
    @Embeddable
    public class UserGroupMembership implements Serializable {
    
        @ManyToOne
        @JoinColumnsOrFormulas(
            value = {
                @JoinColumnOrFormula(column = @JoinColumn(referencedColumnName = "userid", name = "userid")),
                @JoinColumnOrFormula(formula = @JoinFormula(referencedColumnName = "department", value = "department"))
            })
        private User user;
    
        public UserGroupMembership(User user) {
            this.user = user;
        }
    
        public UserGroupMembership() {
        }
    
        public User getUser() {
            return user;
        }
    }
    

    诀窍在于@ManyToOne 允许您使用@JoinColumnsOrFormulas,因此其中一个连接条件可以是一个公式,我似乎不适用于@ManyToMany(@JoinColumnsOrFormulas 注释被忽略,因为它期望连接列作为@JoinTable 注释的一部分)。

    然后将 UserGroupMemberships 映射为 ElementCollection:

        @ElementCollection
        @CollectionTable(name = "user_group", joinColumns = {
            @JoinColumn(name = "department", referencedColumnName = "department"),
            @JoinColumn(name = "groupid", referencedColumnName = "groupid")
        })
        @OrderColumn(name = "seq", nullable = false)
        private List<UserGroupMemberships> groupUsers = new ArrayList<>();
    

    目前这仅适用于单向多对多关系。

    【讨论】: