Given a bidirectional @OneToOne relationship between Parent and Child Entity:
Code:
@Entity
public class Parent {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(unique = true, nullable = false)
private Long id;
@OneToOne(optional = false, mappedBy = "parent", cascade = ALL)
private Child child;
...
}
Code:
@Entity
public class Child {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(unique = true, nullable = false)
private Long id;
@OneToOne(optional=false)
@JoinColumn(nullable=false)
private Parent parent;
...
}
The following test fails with org.hibernate.PropertyValueException: not-null property references a null or transient value: frol.Child.parent
Code:
@Test
public void deleteTest() {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("onetone");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
Parent a = new Parent();
Child b = new Child();
a.setChild(b);
b.setParent(a);
em.persist(a);
em.flush();
em.clear();
a = em.find(Parent.class, a.getId());
em.remove(a);
em.flush(); // fails hier with: org.hibernate.PropertyValueException: not-null property references a null or transient value : frol.Child.parent
}
See also the test case on GitHub: https://github.com/wrungel/bugs/tree/master/onetone-bidirectional-cascade-bug.
I didn't find in JPA spec any restrictions on this kind of association.
Technically this kind of association can be persisted because the foreign key is on child side: first the persistence provider could delete the child and then its parent. But at runtime the deletion order seems to be different.
I found the following workarounds:
mark one end of the association as optional.
make the association unidirectional.
Is this a
bug in Hibernate and I should file a ticket or does it works as designed in JPA?
I use Hibernate 4.3.6.Final.
The problem also with Hibernate 4.1.5.Final but the exception is different. In this version Hibernate tries first to update the foreign key. Setting it to null causes ConsraintViolation because it is not nullable.
Note that I already asked this question on SO:
http://stackoverflow.com/questions/26584474/removing-bidirectional-onetoone-association-with-cascade-on-one-side-and-non-op