Enabling ENABLE_LAZY_LOAD_NO_TRANS results in trying to remove elements in collections

Description

This worked fine in Hibernate-4.1.7 but stopped working in 4.1.8

Iterating over a collection in an Entity outside the transaction (persistence-context) makes org.hibernate.engine.internal.Collections.prepareCollectionForUpdate() think that ownerChanged == true, which results in:

// Collections:252 in Hibernate-4.1.9.Final
entry.setDoremove( true );

This means that Hibernate will silently clear collections and remove data if you access a collection outside the transaction with ENABLE_LAZY_LOAD_NO_TRANS enabled.

As if this is not bad enough, if you have a constraint in the DB preventing this delete, then this results in Hibernate leaking connections because ( ( Session) session ).getTransaction().commit() in AbstractPersistentCollection:241 throws an Exception, resulting in the connection not being closed on line 243.

Attachments

2
  • 19 Jun 2013, 04:24 PM
  • 19 Jun 2013, 04:24 PM

Activity

Show:

Vojtěch Knyttl March 21, 2014 at 10:25 PM

Brilliant, thanks! How long does it take to have this in maven repository?

Steve Ebersole March 21, 2014 at 6:58 PM

Yeah the original test case was not very good in terms of using in the regression suite. It did not assert anything useful..

Aleksander Dukhno March 21, 2014 at 6:46 PM

<face-palm>My mistake is that I thought I should get some kind of Exception</face-palm> according to attached .java file. Thanks for clarification.

Steve Ebersole March 21, 2014 at 6:35 PM

Well that assert failure is the whole point of this bug report...

Aleksander Dukhno March 21, 2014 at 6:33 PM

I didn't get how you fixed my test case.

I removed

for ( Child c : children ) { c.setParent( this ); }

Then do this

Parent p = new Parent(); for ( int i = 0; i < CHILDREN_SIZE; i++ ) { Child c = new Child(); c.setParent( p ); } s.persist( p );

as a result I get java.lang.AssertionError on

assertEquals( CHILDREN_SIZE, loadedPatent.getChildren().size() );

But if I do this

List<Child> children = new ArrayList<Child>(); for ( int i = 0; i < CHILDREN_SIZE; i++ ) { Child c = new Child(); s.persist( c ); lastChildID = c.getId(); children.add( c ); } Parent p = new Parent(); p.setChildren( children ); s.persist( p );

as a result I get a green bar

Where did I make mistake?

Fixed

Details

Assignee

Reporter

Fix versions

Affects versions

Priority

Created February 5, 2013 at 11:40 PM
Updated May 4, 2022 at 6:41 PM
Resolved May 4, 2022 at 6:41 PM