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

Ben*_*n M 13 many-to-many hibernate jpa map

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

 USER      GROUP_USER      GROUP
------    ------------    -------
 id        user_id         id
 name      group_id        name
           createdAt
Run Code Online (Sandbox Code Playgroud)

有以下3个类:

  1. User@OneToMany List<GroupUser>
  2. GroupUser@ManyToOne User@ManyToOne Group
  3. Group@OneToMany List<GroupUser>

它有效,但它很常见的常见用例.例如:给我所有组User user:

List<Group> groups;
for(GroupUser gu : user.getGroupUsers) {
    groups.add(gu.getGroup());
}
Run Code Online (Sandbox Code Playgroud)

然后我想到了使用a的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;
}
Run Code Online (Sandbox Code Playgroud)

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

 USER      GROUP_USER      GROUP
------    ------------    -------
 id        User_id         id
 name      users_KEY       name
           Group_id
           group_KEY
           createdAt
Run Code Online (Sandbox Code Playgroud)

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

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

或者我必须使用@ManyToMany而不是@ElementCollection

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


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

  • 复合主键(Group_id,User_id)

目前它创建了一个复合PK(Group_id,users_KEY),这对我来说似乎很奇怪.并且它也产生4(!!)索引,每列一个User_id,Group_id,users_KEYgroups_KEY.


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

坏事是:我还是不知道为什么 ......

解:

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

@Entity
class User {
   @Column(name="id")
   UUID id;

   @Column(name="name")
   String name;

   @ElementCollection
   @CollectionTable(name="Group_User",
     joinColumns=@JoinColumn(name="User_Id"))
   @MapKeyJoinColumn(name="Group_Id")
   Map<Group, GroupUserRelationData> groups;
}

@Entity
class Group {
   @Column(name="id")
   UUID id;

   @Column(name="name")
   String name;

   @ElementCollection
   @CollectionTable(name="Group_User",
     joinColumns=@JoinColumn(name="Group_Id"))
   @MapKeyJoinColumn(name="User_Id")
   Map<User, GroupUserRelationData> users;
}

@Embeddable
class GroupUserRelationData {
  @Column(name="createdAt")
  DateTime createdAt;
}
Run Code Online (Sandbox Code Playgroud)

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

Vla*_*cea 2

映射需要一对多键和映射键。

在第一个示例中,Hibernate 发现它需要一个 FK 来Group.id匹配GroupUser.group_id加载关联的用户。但是因为您没有指定 Map 键,所以它必须弄清楚从哪里获取它

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

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