在删除元素时,Hibernate中的约束违反与JoinTable和OrderColumn的单向OneToMany映射 [英] Constraint violation in Hibernate unidirectional OneToMany mapping with JoinTable and OrderColumn when removing elements
问题描述
从上面描述的映射列表中删除元素时遇到问题。这里是映射:
@Entity
@Table(name =foo)
class Foo {
私人列表栏;
@OneToMany
@OrderColumn(name =order_index)
@JoinTable(name =foo_bar_map,joinColumns = @JoinColumn(name =foo_id),inverseJoinColumns = @JoinColumn(name =bar_id))
@Fetch(FetchMode.SUBSELECT)
public List getBars(){
return bars;
插入Bar-instances并保存Foo可以正常工作,但是当我从该列表再次保存,违反了映射表中对bar_id的唯一约束。下面的SQL语句是由hibernate发布的,这些看起来很奇怪:
LOG:执行:从foo_bar_map中删除,其中foo_id = $ 1和order_index = $ 2
详细信息:参数:$ 1 ='4',$ 2 ='6'
LOG:执行S_5:更新foo_bar_map set bar_id = $ 1 where foo_id = $ 2 and order_index = $ 3
DETAIL :参数:$ 1 ='88',$ 2 ='4',$ 3 ='0'
错误:重复键值违反唯一约束foo_bar_map_bar_id_key
这个错误是完全有道理的,考虑到Hibernate生成的语句(列表中有五个项目,我删除了第一个项目,Hibernate使用LAST索引删除映射行,并尝试更新剩余的从第一个开始)。
上面的映射有什么问题?
解决方案您的映射完全有效,并且可以与JPA 2.0一起使用(不包含
Fetch
annota当然),但确实因为Hibernate而失败。
以下是带Hibernate的DDL:
create table foo_bar_map( foo_id bigint不为null,bar_id bigint不为null,order_index整数不为空,主键(foo_id,order_index),unique(bar_id))
alter table foo_bar_map添加约束FK14F1CB7FA042E82外键(bar_id)引用Bar4022509
alter table foo_bar_map添加约束FK14F1CB7B6DBCCDC外键(foo_id)引用Foo4022509
让我们来说一下
Foo#1
包含第一栏
,栏#2
,Bar#3
,连接表包含:
foo_id | bar_id | order_index
1 | 1 | 1
1 | 2 | 2
1 | 3 | 3
删除时,从列表中说出第一项,Hibernate首先
delete
连接表的最后一行(WTF?):
foo_id | bar_id | order_index
1 | 1 | 1
1 | 2 | 2
然后尝试
update bar_id
列,而不是order_index
(WTF !?)来反映项目的新顺序在列表中。首先(示意):
foo_id | bar_id | order_index
1 | 2 | 1
1 | 2 | 2
下一步将导致:
foo_id | bar_id | order_index
1 | 2 | 1
1 | 3 | 2
很明显,这种方法听起来不对,不起作用因为
bar_id
上的唯一
约束。更一般地说,为什么Hibernate会混淆bar_id
而不是更新order_index
列?
我认为这是一个Hibernate错误(报告为
HHH-5694,请参阅 HHH- 1268 )。I have a problem when removing elements from a list mapped as described above. Here is the mapping:
@Entity @Table( name = "foo") class Foo { private List bars; @OneToMany @OrderColumn( name = "order_index" ) @JoinTable( name = "foo_bar_map", joinColumns = @JoinColumn( name = "foo_id" ), inverseJoinColumns = @JoinColumn( name = "bar_id" ) ) @Fetch( FetchMode.SUBSELECT ) public List getBars() { return bars; } }Inserting Bar-instances and saving the Foo works fine, but when I remove an element from the list and save again, the unique constraint on bar_id in the mapping table is violated. The following SQL-statements are issued by hibernate, and these look quite odd:
LOG: execute : delete from foo_bar_map where foo_id=$1 and order_index=$2 DETAIL: parameters: $1 = '4', $2 = '6' LOG: execute S_5: update foo_bar_map set bar_id=$1 where foo_id=$2 and order_index=$3 DETAIL: parameters: $1 = '88', $2 = '4', $3 = '0' ERROR: duplicate key value violates unique constraint "foo_bar_map_bar_id_key"The error perfectly makes sense, given the statements generated by Hibernate (there are five items in the list, I remove the first one and Hibernate deletes the mapping row with the LAST index and the tries to updates the remaining ones, starting with the first).
What is wrong with the mapping above?
解决方案Your mapping is totally valid and works with EclipseLink as JPA 2.0 implementation (without the
Fetch
annotation of course), but indeed fails with Hibernate.Here is the DDL with Hibernate:
create table foo_bar_map (foo_id bigint not null, bar_id bigint not null, order_index integer not null, primary key (foo_id, order_index), unique (bar_id)) alter table foo_bar_map add constraint FK14F1CB7FA042E82 foreign key (bar_id) references Bar4022509 alter table foo_bar_map add constraint FK14F1CB7B6DBCCDC foreign key (foo_id) references Foo4022509
So let's say
Foo#1
holds a list withBar#1
,Bar#2
,Bar#3
, the join table contains:foo_id | bar_id | order_index 1 | 1 | 1 1 | 2 | 2 1 | 3 | 3
When removing, say the first item from the list, Hibernate first
delete
the last row (WTF?) from the join table:foo_id | bar_id | order_index 1 | 1 | 1 1 | 2 | 2
And then tries to
update
thebar_id
column in the join table instead of theorder_index
(WTF!?) to reflect the "new" ordering of the items in the list. First (schematically):foo_id | bar_id | order_index 1 | 2 | 1 1 | 2 | 2
where the next step would result in:
foo_id | bar_id | order_index 1 | 2 | 1 1 | 3 | 2
Obviously, this approach doesn't sound right and doesn't work because of the
unique
constraint onbar_id
. More generally, why the hell does Hibernate mess with thebar_id
instead of updating theorder_index
column?I consider this to be an Hibernate bug (reported as
HHH-5694, see HHH-1268 now).这篇关于在删除元素时,Hibernate中的约束违反与JoinTable和OrderColumn的单向OneToMany映射的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!