ManyToMany(带有附加列)使用@ElementCollection和java.util.Map?

时间:2013-09-24 07:19:52

标签: hibernate jpa map many-to-many

我正在尝试优化我的@Entity课程。我们来看一个User <-> Group关系的常见情况。我还想存储建立关系的日期。表格布局:

 USER      GROUP_USER      GROUP
------    ------------    -------
 id        user_id         id
 name      group_id        name
           createdAt

以下3个班级:

  1. User@OneToMany List<GroupUser>
  2. GroupUser@ManyToOne User@ManyToOne Group
  3. Group@OneToMany List<GroupUser>
  4. 它可以工作,但它很常见的常见用例。例如:User user

    提供所有群组
    List<Group> groups;
    for(GroupUser gu : user.getGroupUsers) {
        groups.add(gu.getGroup());
    }
    

    然后我想到了使用Map的想法。所以我创建了以下3个类:

    @Entity
    class User {
       @Column(name="id")
       UUID id;
    
       @Column(name="name")
       String name;
    
       @ElementCollection
       @CollectionTable(name="Group_User")
       Map<Group, GroupUserRelationData> groups;
    }
    
    @Entity
    class Group {
       @Column(name="id")
       UUID id;
    
       @Column(name="name")
       String name;
    
       @ElementCollection
       @CollectionTable(name="Group_User")
       Map<User, GroupUserRelationData> users;
    }
    
    @Embeddable
    class GroupUserRelationData {
      @Column(name="createdAt")
      DateTime createdAt;
    }
    

    确实按预期创建3个表,但Group_User表中的列很奇怪:

     USER      GROUP_USER      GROUP
    ------    ------------    -------
     id        User_id         id
     name      users_KEY       name
               Group_id
               group_KEY
               createdAt
    

    我确信我错过了一些东西......看起来我必须指定JoinColumn。但是正确的方法是什么?

    @CollectionTable(joinColumns=...)@MapKeyColumn@MapKeyJoinColumn之间有何区别?我必须设置所有这些吗?

    或者我是否必须使用@ManyToMany代替@ElementCollection

    我只想使用java.util.Map获得与顶部相同的表格布局。


    编辑#1:此外,数据库之后应该对表格有正确的约束:

    • 复合主键(Group_id,User_id)

    目前它创建了一个复合PK(Group_id,users_KEY),这对我来说似乎很奇怪。它还创建了4个(!!)索引,每列{1}},User_idGroup_idusers_KEY


    编辑#2:我找到了一个网站,告诉我们何时使用哪些注释:http://kptek.wordpress.com/2012/06/26/collection-mapping/

    糟糕的是:我仍然不知道为什么 ......

    解决方案:

    经过一些尝试后,我想出了以下代码,这正是我想要的。我必须使用所有这些注释,否则它会创建其他列:

    groups_KEY

    我仍然希望看到这些注释的确切解释,以及为什么默认行为会创建四个列和一个奇怪的主键。

1 个答案:

答案 0 :(得分:0)

Map需要一对多键和map键。

在您的第一个示例中,Hibernate发现需要Group.id的FK来匹配GroupUser.group_id以加载关联的用户。但是因为你没有指定Map键,所以必须弄明白where to take it from

因此,Hibernate假设您需要@MapKeyColumn,并且由于未指定列名,因此使用属性后跟下划线后跟KEY的名称(例如users_KEY)。

这就是为什么你有这两个额外的列。当您提供@MapKeyJoinColumn(name="User_Id")时,地图知道从哪里拿到钥匙。

相关问题