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) @NotNull 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.
The workaround is to initialize the collection to an empty collection, as in: @OneToMany(mappedBy = "parent", cascade = CascadeType.ALL, orphanRemoval = true) @NotNull 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.
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.