Hibernate fails to delete orphan child if parent is merged and not yet flushed
Description
Activity
Andreas Benneke March 31, 2016 at 9:31 AM
We just verified that the same behavior still exists in 5.1.0.
As explained above I don't think that different handling of children after persist or merge is expected behavior and would like to see this reopened.
Thank you!
Andreas Benneke March 2, 2016 at 6:26 AM
Thank you for looking into this one.
I do not understand how the cited spec explains the different behaviors between persist and merge?
It even underlines, that you can set the relationship to null OR remove the entity from the collection - however doing the first or not leads to different results when using merge or persist in the first place.
Former user March 2, 2016 at 3:39 AM
This is expected behavior.
JPA 2.1 spec, section 2.9 says the following:
"Associations that are specified as OneToOne or OneToMany support use of the orphanRemoval option. The following behaviors apply when orphanRemoval is in effect:
If an entity that is the target of the relationship is removed from the relationship (by setting the
relationship to null or removing the entity from the relationship collection), the remove opera-
tion will be applied to the entity being orphaned.* The remove operation is applied at the time of
the flush operation.*
..."
Andreas Benneke October 28, 2015 at 11:04 AM
Verified that the problem still exists in 4.3.11 und 5.0.2.
Steve Ebersole October 28, 2015 at 3:24 AM
As part of verifying that this issue affects 5.0, please just set the "Affects version". Leave the "verify-affects-5.0" label and leave the issue in "Awaiting Response" status; these are critical for us to be able to track these verifications and triage them. Thanks.
We have a parent-child relation with
@OneToMany(mappedBy = "parent", cascade = CascadeType.ALL, orphanRemoval = true) Set<Child> getChildren()
on the parent-side and
@ManyToOne(optional = false) Parent getParent()
on the children-side. So basically the children cannot exist without a parent.
If we now create a parent with children, add the entities to the entity manager, remove one child and flush those changes, we end up with very different results depending on if we used persist or merge and flushing or not in the first place.
persist works as expected (flushed or not)
merge works only if the initial parent was flushed
If we however merge without flushing, it depends on whether we clear the parent on the child side:
If the parent is not cleared, the orphan child is inserted and effectively not removed as orphanRemoval suggests
If the parent is cleared, Hibernate tries to insert the orphan child into the database and fails with the null reference to the parent
Since both cases work perfectly with persist (instead of merge), we would expect the very same behavior after an initial merge? Is this expectation justified? Or are we doing something wrong?
This may be related with https://hibernate.atlassian.net/browse/HHH-9330#icft=HHH-9330 respectively HHH-9571, at least the DeleteOneToManyOrphansTest test case within that defect has some similarities. That case however is using persist and flush which works perfectly in our case, that's why we opened a new issue on this one.
You may find another very small stripped down test project for these cases on Github https://github.com/abenneke/sandbox/tree/master/hibernate-flush-remove
Thank you!