Hibernate - @ElementCollection - 奇怪的删除/插入行为 [英] Hibernate - @ElementCollection - Strange delete/insert behavior

查看:23
本文介绍了Hibernate - @ElementCollection - 奇怪的删除/插入行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

@Entity
public class Person {

    @ElementCollection
    @CollectionTable(name = "PERSON_LOCATIONS", joinColumns = @JoinColumn(name = "PERSON_ID"))
    private List<Location> locations;

    [...]

}

@Embeddable
public class Location {

    [...]

}

给定以下类结构,当我尝试将新位置添加到人员位置列表时,它总是导致以下 SQL 查询:

Given the following class structure, when I try to add a new location to the list of Person's Locations, it always results in the following SQL queries:

DELETE FROM PERSON_LOCATIONS WHERE PERSON_ID = :idOfPerson

A lotsa' inserts into the PERSON_LOCATIONS table

Hibernate (3.5.x/JPA 2) 删除给定 Person 的所有关联记录,并重新插入所有以前的记录以及新记录.

Hibernate (3.5.x / JPA 2) deletes all associated records for the given Person and re-inserts all previous records, plus the new one.

我认为 Location 上的 equals/hashcode 方法可以解决问题,但它没有改变任何东西.

I had the idea that the equals/hashcode method on Location would solve the problem, but it didn't change anything.

感谢任何提示!

推荐答案

问题在 JPA wikibook 的 ElementCollection 页面中以某种方式解释:

The problem is somehow explained in the page about ElementCollection of the JPA wikibook:

JPA 2.0 规范没有提供一种方法来定义 Id可嵌入.但是,要删除或更新一个元素ElementCollection 映射,一些独特的密钥通常是必需的.除此以外,在每次更新时,JPA 提供者都会需要删除所有内容CollectionTable 用于 Entity,以及然后插入值. 所以,JPA 提供者很可能会假设所有的组合Embeddable 中的字段是唯一的,结合外键(JoinColunm(s)).然而这可能是效率低下,或者只是不可行,如果Embeddable 很大,或者很复杂.

Primary keys in CollectionTable

The JPA 2.0 specification does not provide a way to define the Id in the Embeddable. However, to delete or update a element of the ElementCollection mapping, some unique key is normally required. Otherwise, on every update the JPA provider would need to delete everything from the CollectionTable for the Entity, and then insert the values back. So, the JPA provider will most likely assume that the combination of all of the fields in the Embeddable are unique, in combination with the foreign key (JoinColunm(s)). This however could be inefficient, or just not feasible if the Embeddable is big, or complex.

这正是(粗体部分)这里发生的事情(Hibernate 不会为集合表生成主键,也无法检测集合的什么元素发生了变化,并且从表中删除旧内容以插入新内容)

And this is exactly (the part in bold) what happens here (Hibernate doesn't generate a primary key for the collection table and has no way to detect what element of the collection changed and will delete the old content from the table to insert the new content).

但是,如果您定义了一个 @OrderColumn(指定用于维护列表持久顺序的列 - 这很有意义,因为您使用的是List),Hibernate会创建一个主键(由order列和join列组成)并且可以更新集合表不删除整个内容.

However, if you define an @OrderColumn (to specify a column used to maintain the persistent order of a list - which would make sense since you're using a List), Hibernate will create a primary key (made of the order column and the join column) and will be able to update the collection table without deleting the whole content.

像这样(如果你想使用默认的列名):

Something like this (if you want to use the default column name):

@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 注释"
    • 这篇关于Hibernate - @ElementCollection - 奇怪的删除/插入行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆