我正在尝试优化我的@Entity
课程。我们来看一个User <-> Group
关系的常见情况。我还想存储建立关系的日期。表格布局:
USER GROUP_USER GROUP
------ ------------ -------
id user_id id
name group_id name
createdAt
以下3个班级:
User
与@OneToMany List<GroupUser>
GroupUser
与@ManyToOne User
和@ManyToOne Group
Group
与@OneToMany List<GroupUser>
它可以工作,但它很常见的常见用例。例如:为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:此外,数据库之后应该对表格有正确的约束:
目前它创建了一个复合PK(Group_id,users_KEY),这对我来说似乎很奇怪。它还创建了4个(!!)索引,每列{1}},User_id
,Group_id
和users_KEY
。
编辑#2:我找到了一个网站,告诉我们何时使用哪些注释:http://kptek.wordpress.com/2012/06/26/collection-mapping/
糟糕的是:我仍然不知道为什么 ......
经过一些尝试后,我想出了以下代码,这正是我想要的。我必须使用所有这些注释,否则它会创建其他列:
groups_KEY
我仍然希望看到这些注释的确切解释,以及为什么默认行为会创建四个列和一个奇怪的主键。
答案 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")
时,地图知道从哪里拿到钥匙。