Bug 1245082 - [GSS] (6.4.z) HHH-9979 Merged transient entity may not contain some associations when passed to PrePersist/PostPersist callbacks
Summary: [GSS] (6.4.z) HHH-9979 Merged transient entity may not contain some associati...
Alias: None
Product: JBoss Enterprise Application Platform 6
Classification: JBoss
Component: Hibernate
Version: 6.3.3
Hardware: Unspecified
OS: Unspecified
Target Milestone: ---
: ---
Assignee: Gail Badner
QA Contact: Martin Simka
Depends On:
TreeView+ depends on / blocked
Reported: 2015-07-21 07:45 UTC by Fedor Gavrilov
Modified: 2019-08-15 04:55 UTC (History)
6 users (show)

Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Clone Of:
Last Closed: 2015-10-13 09:53:44 UTC
Type: Bug

Attachments (Terms of Use)
arquillian test (7.10 KB, application/x-gzip)
2015-07-21 07:45 UTC, Fedor Gavrilov
no flags Details

Description Fedor Gavrilov 2015-07-21 07:45:32 UTC
Created attachment 1054220 [details]
arquillian test

Description of problem:
"null" is always passed to the validator during a merge operation, even when the collection is non-empty, causing this operation to fail with C.V.E.

Version-Release number of selected component (if applicable):
EAP: 6.3.3
hibernate: 4.2.14.SP1-redhat-1 & 4.3.10-Final

How reproducible:
The testcase has two entities: Parent and Child. The Parent entity has a list of children that are automatically cascaded during entity manager operations and we always want the list to be non-null, so the relationship from Parent to Child has the following annotations:
@OneToMany(mappedBy = "parent", cascade = CascadeType.ALL, orphanRemoval = true)
private List<Child> children;

Steps to Reproduce:
Test class contains two JUnit tests, one where we to save a new valid Parent and Child with the EntityManager.persist operation and one where we try to save it with the EntityManager.merge operation. The persist works as we would expect, the @NotNull validation passes, however the merge operation throws a ConstraintValidationException telling us that the list of children was null even when the parent had a valid list with one child in it.

Actual results:
Test with merge fails with C.V.E.

Expected results:
Both tests passed

Additional info:
After inspecting the source code of Hibernate we suspect the problem comes from the "org.hibernate.event.internal.DefaultMergeEventListener.entityIsTransient" method. Inside that method the transient Parent entity is copied into a new object, but Hibernate does not copy the OneToMany assocation to Child because the Parent object is not the owning side of the relationship. It then tries to perform validation of this copy but this fails because the OneToMany assocation is still "null".
If we remove the @NotNull annotation the operation passes and the Parent and Child are correctly saved to the database, so it seems like the problem is just that the bean validation is called at the wrong moment.
Test against another JPA provider worked fine.

Comment 4 Gail Badner 2015-07-27 19:10:35 UTC
The workaround is to initialize the collection to an empty collection, as in:

@OneToMany(mappedBy = "parent", cascade = CascadeType.ALL, orphanRemoval = true)
private List<Child> children = new ArrayList<Child>();

This way, when Hibernate instantiates the entity during the merge process, the collection will be instantiated in a valid state.

Comment 5 Gail Badner 2015-07-27 22:12:45 UTC
Another workaround is to not use an identity column for the ID.

When Hibernate uses a "post-insert" ID (which requires inserting the entity in order to retrieve the ID), any inserts that are queued as well as the entity with the post-insert ID are inserted immediately in order to obtain the ID value.

When the ID is not a "post-insert" ID, then the entity insert is delayed as long as possible, until either an entity with a post-insert ID is persisted or the next flush, whichever is sooner.

Note You need to log in before you can comment on or make changes to this bug.