我有一个具有可嵌入地址的Person实体,它们之间存在一对多的关系(一个人可以有多个地址)。当前的映射是这样的:
@Embeddable
public class Address {
// ... attributes
}
@Entity
public class Person {
@ElementCollection(fetch = FetchType.EAGER)
@JoinTable(name = "Person_addresses", joinColumns = @JoinColumn(name = "personid")
)
/*
Attribute ovverrides with annotations
*/
private java.util.Set<Address> addresses = new java.util.HashSet<Address>();
}
使用此注释意味着在数据库中我有一个Person_addresses表,其中包含所有地址属性和personid。但这也意味着如果我有一个人有地址列表并更新地址列表,Hibernate会删除所有相关记录并再次插入它们(修改后的记录)。
据我所知,有一种方法可以在此表中为每条记录创建一个主键 - 在这种情况下,hibernate可以决定需要更新列表中的哪个项目。所以我的问题是,如何在加入表中映射带有标识符的可嵌入列表? (我希望我想要的是可以理解的:))。
答案 0 :(得分:2)
http://en.wikibooks.org/wiki/Java_Persistence/ElementCollection#Primary_keys_in_CollectionTable
JPA 2.0规范没有提供定义Id的方法 可嵌入的。但是,删除或更新元素 ElementCollection映射通常需要一些唯一键。 否则,在每次更新时,JPA提供程序都需要删除 来自实体的CollectionTable的所有内容,然后插入 价值回来了。因此,JPA提供商很可能会认为 Embeddable中所有字段的组合都是独一无二的 与外键组合(JoinColumn(s))。然而,这可以 如果Embeddable很大,那么效率低下,或者说不可行 复杂。某些JPA提供程序可能允许在中指定Id 可嵌入,解决此问题。请注意,在这种情况下,Id只需要 对于集合而言是唯一的,而不是表,就像外键一样 包括在内。有些人还可能允许CollectionTable上的唯一选项 用于此。否则,如果您的Embeddable很复杂,您可以 考虑将其变为实体并改为使用OneToMany。
就这样,它无法完成。
答案 1 :(得分:2)
正如maestro的回复所暗示的,唯一可移植的解决方案是将其转换为使用实体和一对多。
也就是说,Hibernate有一个名为&#34; id bag&#34;的非规范功能。它允许您使用每行的标识符映射基本或可嵌入的集合,从而为您提供所需的有效更新:
@Entity
public class Person {
@CollectionId( columns={"address_id"}, type="int", generator="increment" )
@ElementCollection(fetch = FetchType.EAGER)
@JoinTable(name = "Person_addresses", joinColumns = @JoinColumn(name = "personid"))
private java.util.List<Address> addresses = new java.util.ArrayList<Address>();
}
请注意,从Set切换到List。还要注意生成的表结构......看起来很像实体;)