@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 方法可以解决问题,但它并没有改变任何东西。
感谢任何提示!
最佳答案
JPA wikibook 的 ElementCollection
页面以某种方式解释了该问题:
Primary keys in CollectionTable
The JPA 2.0 specification does not provide a way to define the
Id
in theEmbeddable
. However, to delete or update a element of theElementCollection
mapping, some unique key is normally required. Otherwise, on every update the JPA provider would need to delete everything from theCollectionTable
for theEntity
, and then insert the values back. So, the JPA provider will most likely assume that the combination of all of the fields in theEmbeddable
are unique, in combination with the foreign key (JoinColunm
(s)). This however could be inefficient, or just not feasible if theEmbeddable
is big, or complex.
这正是(粗体部分)这里发生的事情(Hibernate 不会为集合表生成主键,也无法检测到集合的哪些元素发生了变化,并且将从表中删除旧内容以插入新内容)。
但是,if 您定义了一个 @OrderColumn
(指定用于维护列表的持久顺序的列 - 因为您使用的是List
),Hibernate 将创建一个 主键(由 order 列和 join 列组成)并能够更新集合表不删除整个内容。
类似这样的东西(如果你想使用默认的列名):
@Entity
public class Person {
...
@ElementCollection
@CollectionTable(name = "PERSON_LOCATIONS", joinColumns = @JoinColumn(name = "PERSON_ID"))
@OrderColumn
private List<Location> locations;
...
}
引用文献
- JPA 2.0 规范
- 第 11.1.12 节“ElementCollection 注释”
- 第 11.1.39 节“OrderColumn 注释”
- JPA 维基书
关于java - Hibernate - @ElementCollection - 奇怪的删除/插入行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3742897/