HHH-12425 Move afterInitialize() phase after the collection initialization

This commit is contained in:
Guillaume Smet 2018-10-15 17:24:53 +02:00
parent 05d538ee15
commit 3fec3b930b
5 changed files with 141 additions and 4 deletions

View File

@ -284,8 +284,6 @@ public final class TwoPhaseLoad {
persistenceContext.setEntryStatus( entityEntry, Status.MANAGED );
}
persister.afterInitialize( entity, session );
if ( debugEnabled ) {
LOG.debugf(
"Done materializing entity %s",
@ -298,6 +296,22 @@ public final class TwoPhaseLoad {
}
}
/**
* Perform the afterInitialize() step. This needs to be done after the collections have been properly initialized
* thus a separate step.
*
* @param entity The entity being loaded
* @param session The Session
*/
public static void afterInitialize(
final Object entity,
final SharedSessionContractImplementor session) {
final PersistenceContext persistenceContext = session.getPersistenceContext();
final EntityEntry entityEntry = persistenceContext.getEntry( entity );
entityEntry.getPersister().afterInitialize( entity, session );
}
/**
* Check if eager of the association is overriden by anything.
*

View File

@ -1164,6 +1164,12 @@ public abstract class Loader {
}
}
if ( hydratedObjects != null ) {
for ( Object hydratedObject : hydratedObjects ) {
TwoPhaseLoad.afterInitialize( hydratedObject, session );
}
}
// 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

View File

@ -211,6 +211,9 @@ public abstract class AbstractRowReader implements RowReader {
// now we can finalize loading collections
finishLoadingCollections( context );
// and trigger the afterInitialize() hooks
afterInitialize( context, hydratedEntityRegistrations );
// finally, perform post-load operations
postLoad( postLoadEvent, context, hydratedEntityRegistrations, afterLoadActionList );
}
@ -250,6 +253,17 @@ public abstract class AbstractRowReader implements RowReader {
}
}
private void afterInitialize(ResultSetProcessingContextImpl context,
List<HydratedEntityRegistration> hydratedEntityRegistrations) {
if ( hydratedEntityRegistrations == null ) {
return;
}
for ( HydratedEntityRegistration registration : hydratedEntityRegistrations ) {
TwoPhaseLoad.afterInitialize( registration.getInstance(), context.getSession() );
}
}
private void postLoad(
PostLoadEvent postLoadEvent,
ResultSetProcessingContextImpl context,

View File

@ -0,0 +1,102 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.bytecode.enhancement.lazy;
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
import java.util.LinkedHashSet;
import java.util.Set;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.MappedSuperclass;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.junit.Test;
import org.junit.runner.RunWith;
@TestForIssue(jiraKey = "")
@RunWith(BytecodeEnhancerRunner.class)
public class LazyCollectionHandlingTest extends BaseCoreFunctionalTestCase {
private Integer id;
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class[]{
JafSid.class, UserGroup.class
};
}
@Test
public void test() {
doInHibernate( this::sessionFactory, s -> {
JafSid sid = new JafSid();
s.save( sid );
s.flush();
s.clear();
this.id = sid.getId();
});
doInHibernate( this::sessionFactory, s -> {
s.get( JafSid.class, this.id );
} );
}
@MappedSuperclass
public abstract static class DatabaseEntity {
private int id;
@Id
@GeneratedValue
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
@Entity(name = "JafSid")
public static class JafSid extends DatabaseEntity {
private Set<UserGroup> groups = new LinkedHashSet<>();
@ManyToMany(mappedBy = "members", fetch = FetchType.EAGER)
public Set<UserGroup> getGroups() {
return groups;
}
public void setGroups(Set<UserGroup> groups) {
this.groups = groups;
}
}
@Entity(name = "UserGroup")
public static class UserGroup extends DatabaseEntity {
private Set<JafSid> members = new LinkedHashSet<>();
@ManyToMany
public Set<JafSid> getMembers() {
return members;
}
public void setMembers(Set<JafSid> members) {
this.members = members;
}
}
}

View File

@ -356,6 +356,7 @@ public class CustomPersister implements EntityPersister {
session,
new PreLoadEvent( (EventSource) session )
);
TwoPhaseLoad.afterInitialize( clone, session );
TwoPhaseLoad.postLoad( clone, session, new PostLoadEvent( (EventSource) session ) );
}
return clone;