从如上所述映射的列表中删除元素时出现问题。这是映射:
@实体 @Table(name =“ foo”) Foo类{ 私人列表栏; @OneToMany @OrderColumn(name =“ order_index”) @JoinTable(name =“ foo_bar_map”,joinColumns = @JoinColumn(name =“ foo_id”),inverseJoinColumns = @JoinColumn(name =“ bar_id”))) @Fetch(FetchMode.SUBSELECT) 公共列表getBars(){ 回条 } }
插入Bar实例并保存Foo效果很好,但是当我从列表中删除一个元素并再次保存时,映射表中对bar_id的唯一约束被违反。以下SQL语句是由hibernate发出的,这些看起来很奇怪:
日志:执行:从foo_bar_map中删除,其中foo_id = $ 1和order_index = $ 2 详细信息:参数:$ 1 ='4',$ 2 ='6' 日志:执行S_5:更新foo_bar_map设置bar_id = $ 1,其中foo_id = $ 2和order_index = $ 3 详细信息:参数:$ 1 ='88',$ 2 ='4',$ 3 ='0' 错误:重复的键值违反了唯一约束“ foo_bar_map_bar_id_key”
考虑到Hibernate生成的语句,该错误完全有意义(列表中有五个项目,我删除了第一个项目,Hibernate删除了具有LAST索引的映射行,并尝试从第一个开始更新其余的行) 。
上面的映射有什么问题?
您的映射是完全有效的,并且可以作为JPA 2.0实现与EclipseLink一起使用(Fetch当然没有注释),但是对于Hibernate而言确实失败。
Fetch
这是带有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#1
Bar#1
Bar#2
Bar#3
foo_id | bar_id | order_index 1 | 1 | 1 1 | 2 | 2 1 | 3 | 3
删除时,说出列表中的第一项,Hibernate首先delete进入连接表的最后一行(WTF?):
delete
foo_id | bar_id | order_index 1 | 1 | 1 1 | 2 | 2
然后尝试连接表中update的bar_id列而不是order_index(WTF !?),以反映列表中项目的“新”顺序。首先(示意):
update
bar_id
order_index
foo_id | bar_id | order_index 1 | 2 | 1 1 | 2 | 2
下一步将导致:
foo_id | bar_id | order_index 1 | 2 | 1 1 | 3 | 2
显然,由于的限制,这种方法听起来不正确, 也不起作用 。更笼统地说,为什么Hibernate搞砸了而不是更新该列呢?unique``bar_id``bar_id``order_index
unique``bar_id``bar_id``order_index
我认为这是一个Hibernate错误(报告为 HHH-5694 ,现在参见HHH-1268)。