Assume a simple bi-directional one-to-one relation A->B where B is the owning side of the association and A.b has an "all" cascade:
{code} @Entity @Table( "table_a") class A { @Id @Column( name = "id") private int id; @OneToOne(mappedBy = "a", cascade = CascadeType.ALL) private B b; }
@Entity @Table( "table_b") class B { @Id @OneToOne @JoinColumn( name = "a_id" ) private A a; } {code}
On the database there's then a foreign key constraint on "table_b _table_b . a_id" a_id_ to _table_a . id_.
We then create a new instance like this: {code} A a = new A(); a.setB( new B() ); a.getB().setA( a );
em.persist( a ) ; {code}
With hibernate.order_inserts = false this works as intended, i.e. first A is persisted and then B due to the cascade.
However, with hibernate.order_inserts = true this breaks because the insert actions are incorrectly reordered thus violating the foreign key constraint. The problem seems to be in _org.hibernate.engine.spi.ActionQueue.InsertActionSorter# addParentChildEntityNames(AbstractEntityInsertAction, BatchIdentifier)_ where there's this piece of code:
{code} if ( type.isEntityType() && value != null ) { EntityType entityType = (EntityType) type; String entityName = entityType.getName(); batchIdentifier.getParentEntityNames().add( entityName ); } {code}
Here the problem is that the type for _A.b_ is OneToOne which is an EntityType and hence B is assumed to be the parent of A. In a sense this is true since B is the owning side of the association but in terms of insert ordering A is the parent of B, i.e. A must be inserted first (as will be done without reordering).
One way to fix this might be to check for OneToOneType and then for the value of foreignKeyType.
Tested against versions 5.2.5 and 5.2.7 but might fail in others as well. |
|