See the original project in the attachment. I have an entity B, which owns an entity A in a 1-to-1 relationship. A may exist without B, but not vice-versa. Besides, multiple instances of C may be associated with B, though instances of C may also exist without being related to B. I have marked B with CascadeType.All and enabled orphan removal in A, C is marked with CascadeType.All end orphan removal enabled on B as follows:
class A { ID id; @OneToOne ( mappedBy = "A", orphanRemoval=true, cascade = CascadeType.ALL) B b; }
class B { ID id; @NotNull @OneToOne (optional = false) @JoinColumn(name = "a_id", nullable = false, referencedColumnName = "id" updatable = true, unique = true) A a; @OneToMany ( fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true) @JoinTable(name="B_to_C", joinColumns = @JoinColumn(name="B_id", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name="C_id", referencedColumnName="id")) Set<C> listOfCs;}
Following will now fail:
A a = new A(); B b = new B(); b.setCList(getABunchOfTransientCsByMagic()); a.setB(b); b.setA(a); a = aRepository.save(A); a.setB(null); aRepository.save(a);
The last statement will fail for hurting the fk constraint lying on b_id in the b_to_c join table. The reason for this is, that Hibernate is putting the delete actions (deletion of B, B_to_C and C) in the wrong order. Debugging showed, that in the session's action queue B is deleted first, then the entries in B_to_C and finally the C instances. The funny thing about this is, that if A is owning B, everything just works fine (B_to_C table is deleted before B is accessed).
|