HHH-6043 PostLoad method invoked before collection initialised

This commit is contained in:
brmeyer 2012-09-26 00:19:05 -04:00
parent ff76c1770a
commit 90a3859c27
4 changed files with 49 additions and 17 deletions

View File

@ -280,19 +280,6 @@ public final class TwoPhaseLoad {
session session
); );
if ( session.isEventSource() ) {
postLoadEvent.setEntity( entity ).setId( id ).setPersister( persister );
final EventListenerGroup<PostLoadEventListener> listenerGroup = session
.getFactory()
.getServiceRegistry()
.getService( EventListenerRegistry.class )
.getEventListenerGroup( EventType.POST_LOAD );
for ( PostLoadEventListener listener : listenerGroup.listeners() ) {
listener.onPostLoad( postLoadEvent );
}
}
if ( LOG.isDebugEnabled() ) { if ( LOG.isDebugEnabled() ) {
LOG.debugf( LOG.debugf(
"Done materializing entity %s", "Done materializing entity %s",
@ -304,6 +291,45 @@ public final class TwoPhaseLoad {
factory.getStatisticsImplementor().loadEntity( persister.getEntityName() ); factory.getStatisticsImplementor().loadEntity( persister.getEntityName() );
} }
} }
/**
* PostLoad cannot occur during initializeEntity, as that call occurs *before*
* the Set collections are added to the persistence context by Loader.
* Without the split, LazyInitializationExceptions can occur in the Entity's
* postLoad if it acts upon the collection.
*
*
* HHH-6043
*
* @param entity
* @param session
* @param postLoadEvent
*/
public static void postLoad(
final Object entity,
final SessionImplementor session,
final PostLoadEvent postLoadEvent) {
if ( session.isEventSource() ) {
final PersistenceContext persistenceContext
= session.getPersistenceContext();
final EntityEntry entityEntry = persistenceContext.getEntry(entity);
final Serializable id = entityEntry.getId();
postLoadEvent.setEntity( entity ).setId( entityEntry.getId() )
.setPersister( entityEntry.getPersister() );
final EventListenerGroup<PostLoadEventListener> listenerGroup
= session
.getFactory()
.getServiceRegistry()
.getService( EventListenerRegistry.class )
.getEventListenerGroup( EventType.POST_LOAD );
for ( PostLoadEventListener listener : listenerGroup.listeners() ) {
listener.onPostLoad( postLoadEvent );
}
}
}
private static boolean useMinimalPuts(SessionImplementor session, EntityEntry entityEntry) { private static boolean useMinimalPuts(SessionImplementor session, EntityEntry entityEntry) {
return ( session.getFactory().getSettings().isMinimalPutsEnabled() && return ( session.getFactory().getSettings().isMinimalPutsEnabled() &&

View File

@ -1031,7 +1031,16 @@ public abstract class Loader {
} }
} }
} }
// Until this entire method is refactored w/ polymorphism, postLoad was
// split off from initializeEntity. It *must* occur after
// endCollectionLoad to ensure the collection is in the
// persistence context.
if ( hydratedObjects!=null ) {
for ( Object hydratedObject : hydratedObjects ) {
TwoPhaseLoad.postLoad( hydratedObject, session, post );
}
}
} }
private void endCollectionLoad( private void endCollectionLoad(

View File

@ -35,7 +35,6 @@ public class Parent {
} }
public void setChildren(Set<Child> children) { public void setChildren(Set<Child> children) {
this.children = children; this.children = children;
//children.size(); // This will result in the same exception as the PostLoad method...
} }
@PostLoad @PostLoad

View File

@ -8,7 +8,6 @@ import java.util.Set;
import javax.persistence.EntityManager; import javax.persistence.EntityManager;
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
import org.hibernate.testing.FailureExpected;
import org.hibernate.testing.TestForIssue; import org.hibernate.testing.TestForIssue;
import org.junit.Test; import org.junit.Test;
@ -20,7 +19,6 @@ public class PostLoadTest extends BaseEntityManagerFunctionalTestCase {
* access the association. * access the association.
*/ */
@Test @Test
@FailureExpected( jiraKey="HHH-6043" )
public void testAccessAssociatedSetInPostLoad() { public void testAccessAssociatedSetInPostLoad() {
Child child = new Child(); Child child = new Child();
child.setId(1); child.setId(1);