| 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:
@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;
}
We then create a new instance like this:
A a = new A();
a.setB( new B() );
a.getB().setA( a );
em.persist( a ) ;
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. The problem seems to be in org.hibernate.engine.spi.ActionQueue.InsertActionSorter# addParentChildEntityNames(AbstractEntityInsertAction, BatchIdentifier) where there's this piece of code:
if ( type.isEntityType() && value != null ) {
EntityType entityType = (EntityType) type;
String entityName = entityType.getName();
batchIdentifier.getParentEntityNames().add( entityName );
}
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. |