@Entity public class Person {
@ElementCollection @CollectionTable(name = "PERSON_LOCATIONS", joinColumns = @JoinColumn(name = "PERSON_ID")) private List<Location> locations; [...] } @Embeddable public class Location { [...] }
给定以下类结构,当我尝试将新位置添加到“人的位置”列表中时,它总是导致以下SQL查询:
DELETE FROM PERSON_LOCATIONS WHERE PERSON_ID = :idOfPerson
和
A lotsa' inserts into the PERSON_LOCATIONS table
Hibernate(3.5.x / JPA 2)删除给定Person的所有关联记录,然后重新插入所有以前的记录以及新的记录。
我有一个想法,即Location上的equals / hashcode方法可以解决此问题,但是它没有任何改变。
任何提示表示赞赏!
在有关ElementCollectionJPA Wikibook 的页面中以某种方式解释了该问题:
ElementCollection
CollectionTable中的主键 JPA 2.0规范不提供一种方式来定义Id在 Embeddable。 但是,要删除或更新ElementCollection映射的元素, 通常需要一些唯一的键。否则,在每次更新的JPA的供应商将需要删除一切从 CollectionTable的Entity,然后插入值回。因此,JPA提供程序将最有可能假定中的所有字段的Embeddable组合与外键组合是唯一的JoinColunm。但是,这可能效率低下,或者如果Embeddable规模较大或过于复杂,那将是不可行的。
CollectionTable中的主键
JPA 2.0规范不提供一种方式来定义Id在 Embeddable。 但是,要删除或更新ElementCollection映射的元素, 通常需要一些唯一的键。否则,在每次更新的JPA的供应商将需要删除一切从 CollectionTable的Entity,然后插入值回。因此,JPA提供程序将最有可能假定中的所有字段的Embeddable组合与外键组合是唯一的JoinColunm。但是,这可能效率低下,或者如果Embeddable规模较大或过于复杂,那将是不可行的。
Id
Embeddable
CollectionTable
Entity
JoinColunm
而这恰好是这里的内容(粗体部分)(Hibernate不会为集合表生成主键,也无法检测集合中 哪些元素 已更改,并且将删除表中的旧内容以插入新内容)。
但是, 如果 定义一个@OrderColumn(以指定用于维护列表的持久顺序的列- 由于使用List,这将很有意义),则Hibernate将创建一个 主键 (由 order列和join列组成 )并且能够在不删除全部内容的情况下更新收藏表。
@OrderColumn
List
这样的事情(如果您想使用默认的列名):
@Entity public class Person { ... @ElementCollection @CollectionTable(name = "PERSON_LOCATIONS", joinColumns = @JoinColumn(name = "PERSON_ID")) @OrderColumn private List<Location> locations; ... }