Constraint violation in Hibernate unidirectional OneToMany mapping with JoinTable and OrderColumn when removing elements

后端 未结 4 1244
小鲜肉
小鲜肉 2020-12-28 17:26

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          


        
相关标签:
4条回答
  • 2020-12-28 17:31

    Usually when joining through a join table the relationship is ManyToMany not OneToMany. Try this

    @ManyToMany
    @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;
    }
    
    0 讨论(0)
  • 2020-12-28 17:36

    I guess what you need is correct inverse mapping.
    http://docs.jboss.org/hibernate/core/3.3/reference/en/html/tutorial.html#tutorial-associations-bidirectional

    0 讨论(0)
  • 2020-12-28 17:36

    No I don't think it's a hibernate bug, and as you will see if you do searches this hibernate bug quoted by Pascal Thivent is a bug known since 2006 and has never been solved.

    Why ?

    Cause I think the problem is just in the constraints on the table and not in hibernate.

    I don't understand why there is a unique constraint on bar_id

    Using an order index means your collection is a List (and not a Set !). And a List is a collection where you can specify index to elements you add (it corresponds to OrderColumn).
    The difference between a List and a Set is that you and can the same data twice (or more), but the same data will be at different indexes. Then you can have the same bar_id a different indexes, you don't have to specify a unique constraint on bar_id. And the primary key can't be (foo_id, order_index) cause the pattern List authorize the same data at different indexes. Maybe your PK should be (foo_id, bar_id, order_index) ?

    I think the problem is in this way :)

    0 讨论(0)
  • 2020-12-28 17:52

    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).

    0 讨论(0)
提交回复
热议问题