从如上所述映射的列表中删除元素时遇到问题。这是映射:
@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; } }
插入 Bar 实例并保存 Foo 工作正常,但是当我从列表中删除一个元素并再次保存时,违反了映射表中 bar_id 的唯一约束。下面的 SQL 语句是由 hibernate 发出的,这些看起来很奇怪:
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"
鉴于 Hibernate 生成的语句(列表中有五个项目,我删除了第一个,Hibernate 删除了具有 LAST 索引的映射行并尝试更新其余的,从第一个)。
上面的映射有什么问题?
最佳答案
您的映射是完全有效的,并且可以作为 JPA 2.0 实现与 EclipseLink 一起使用(当然没有 Fetch
注释),但确实与 Hibernate 一起失败。
这是 Hibernate 的 DDL:
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
假设 Foo#1
包含一个包含 Bar#1
、Bar#2
、Bar#3的列表
,连接表包含:
foo_id | bar_id | order_index
1 | 1 | 1
1 | 2 | 2
1 | 3 | 3
当删除时,比如列表中的第一项,Hibernate 首先从连接表中删除
最后一行(WTF?):
foo_id | bar_id | order_index
1 | 1 | 1
1 | 2 | 2
然后尝试更新
连接表中的bar_id
列而不是order_index
(WTF!?)以反射(reflect)“新"列表中项目的排序。首先(示意图):
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
上的 unique
约束,这种方法听起来不对并且不起作用。更一般地说,为什么 Hibernate 搞砸了 bar_id
而不是更新 order_index
列?
关于java - 删除元素时使用 JoinTable 和 OrderColumn 的 Hibernate 单向 OneToMany 映射中的约束违规,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4022509/