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
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;
}
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
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 :)
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).