一尘不染

删除元素时使用JoinTable和OrderColumn在Hibernate单向OneToMany映射中违反约束

hibernate

从如上所述映射的列表中删除元素时出现问题。这是映射:

@实体
@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索引的映射行,并尝试从第一个开始更新其余的行)

上面的映射有什么问题?


阅读 236

收藏
2020-06-20

共1个答案

一尘不染

您的映射是完全有效的,并且可以作为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#1Bar#2Bar#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

然后尝试连接表中updatebar_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

显然,由于的限制,这种方法听起来不正确, 也不起作用
。更笼统地说,为什么Hibernate搞砸了而不是更新该列呢?unique``bar_id``bar_id``order_index

我认为这是一个Hibernate错误(报告为
HHH-5694
,现在参见HHH-1268)。

2020-06-20