在删除元素时,Hibernate中的约束违反与JoinTable和OrderColumn的单向OneToMany映射 [英] Constraint violation in Hibernate unidirectional OneToMany mapping with JoinTable and OrderColumn when removing elements

查看:125
本文介绍了在删除元素时,Hibernate中的约束违反与JoinTable和OrderColumn的单向OneToMany映射的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

从上面描述的映射列表中删除元素时遇到问题。这里是映射:

 
@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 with Bar#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 the bar_id column in the join table instead of the order_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 on bar_id. More generally, why the hell does Hibernate mess with the bar_id instead of updating the order_index column?

I consider this to be an Hibernate bug (reported as HHH-5694, see HHH-1268 now).

这篇关于在删除元素时,Hibernate中的约束违反与JoinTable和OrderColumn的单向OneToMany映射的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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