Fix initializer post load call timing
This commit is contained in:
parent
e9e81eeda3
commit
7e34535cfe
|
@ -28,8 +28,6 @@ import org.hibernate.event.service.spi.EventListenerGroup;
|
||||||
import org.hibernate.event.service.spi.EventListenerRegistry;
|
import org.hibernate.event.service.spi.EventListenerRegistry;
|
||||||
import org.hibernate.event.spi.EventSource;
|
import org.hibernate.event.spi.EventSource;
|
||||||
import org.hibernate.event.spi.EventType;
|
import org.hibernate.event.spi.EventType;
|
||||||
import org.hibernate.event.spi.PostLoadEvent;
|
|
||||||
import org.hibernate.event.spi.PostLoadEventListener;
|
|
||||||
import org.hibernate.event.spi.PreLoadEvent;
|
import org.hibernate.event.spi.PreLoadEvent;
|
||||||
import org.hibernate.event.spi.PreLoadEventListener;
|
import org.hibernate.event.spi.PreLoadEventListener;
|
||||||
import org.hibernate.internal.util.StringHelper;
|
import org.hibernate.internal.util.StringHelper;
|
||||||
|
@ -540,19 +538,18 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
|
||||||
instance
|
instance
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
final LoadingEntityEntry loadingEntry = new LoadingEntityEntry(
|
|
||||||
this,
|
|
||||||
entityKey,
|
|
||||||
concreteDescriptor,
|
|
||||||
instance
|
|
||||||
);
|
|
||||||
|
|
||||||
rowProcessingState.getJdbcValuesSourceProcessingState().registerLoadingEntity(
|
|
||||||
entityKey,
|
|
||||||
loadingEntry
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final LoadingEntityEntry loadingEntry = new LoadingEntityEntry(
|
||||||
|
this,
|
||||||
|
entityKey,
|
||||||
|
concreteDescriptor,
|
||||||
|
instance
|
||||||
|
);
|
||||||
|
rowProcessingState.getJdbcValuesSourceProcessingState().registerLoadingEntity(
|
||||||
|
entityKey,
|
||||||
|
loadingEntry
|
||||||
|
);
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -578,11 +575,9 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
|
||||||
);
|
);
|
||||||
intializeEntity( instance, rowProcessingState, session, persistenceContext );
|
intializeEntity( instance, rowProcessingState, session, persistenceContext );
|
||||||
hibernateLazyInitializer.setImplementation( instance );
|
hibernateLazyInitializer.setImplementation( instance );
|
||||||
postLoad( instance, rowProcessingState );
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
intializeEntity( entityInstance, rowProcessingState, session, persistenceContext );
|
intializeEntity( entityInstance, rowProcessingState, session, persistenceContext );
|
||||||
postLoad( entityInstance, rowProcessingState );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -808,29 +803,6 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void postLoad(Object instance,RowProcessingState rowProcessingState) {
|
|
||||||
final SharedSessionContractImplementor session = rowProcessingState.getJdbcValuesSourceProcessingState().getSession();
|
|
||||||
|
|
||||||
if ( session instanceof EventSource ) {
|
|
||||||
final PostLoadEvent postLoadEvent = rowProcessingState.getJdbcValuesSourceProcessingState().getPostLoadEvent();
|
|
||||||
assert postLoadEvent != null;
|
|
||||||
|
|
||||||
postLoadEvent.reset();
|
|
||||||
|
|
||||||
postLoadEvent.setEntity( instance )
|
|
||||||
.setId( entityKey.getIdentifier() )
|
|
||||||
.setPersister( concreteDescriptor );
|
|
||||||
|
|
||||||
final EventListenerGroup<PostLoadEventListener> listenerGroup = entityDescriptor.getFactory()
|
|
||||||
.getServiceRegistry()
|
|
||||||
.getService( EventListenerRegistry.class )
|
|
||||||
.getEventListenerGroup( EventType.POST_LOAD );
|
|
||||||
for ( PostLoadEventListener listener : listenerGroup.listeners() ) {
|
|
||||||
listener.onPostLoad( postLoadEvent );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EntityPersister getConcreteDescriptor() {
|
public EntityPersister getConcreteDescriptor() {
|
||||||
return concreteDescriptor;
|
return concreteDescriptor;
|
||||||
|
|
|
@ -181,9 +181,6 @@ public class StandardRowReader<T> implements RowReader<T> {
|
||||||
for ( int i = 0; i < initializers.size(); i++ ) {
|
for ( int i = 0; i < initializers.size(); i++ ) {
|
||||||
initializers.get( i ).endLoading( processingState.getExecutionContext() );
|
initializers.get( i ).endLoading( processingState.getExecutionContext() );
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo : use Callback to execute AfterLoadActions
|
|
||||||
// todo : another option is to use Callback to execute the AfterLoadActions after each row
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -15,8 +15,12 @@ import java.util.function.BiConsumer;
|
||||||
import org.hibernate.engine.spi.CollectionKey;
|
import org.hibernate.engine.spi.CollectionKey;
|
||||||
import org.hibernate.engine.spi.EntityKey;
|
import org.hibernate.engine.spi.EntityKey;
|
||||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||||
|
import org.hibernate.event.service.spi.EventListenerGroup;
|
||||||
|
import org.hibernate.event.service.spi.EventListenerRegistry;
|
||||||
import org.hibernate.event.spi.EventSource;
|
import org.hibernate.event.spi.EventSource;
|
||||||
|
import org.hibernate.event.spi.EventType;
|
||||||
import org.hibernate.event.spi.PostLoadEvent;
|
import org.hibernate.event.spi.PostLoadEvent;
|
||||||
|
import org.hibernate.event.spi.PostLoadEventListener;
|
||||||
import org.hibernate.event.spi.PreLoadEvent;
|
import org.hibernate.event.spi.PreLoadEvent;
|
||||||
import org.hibernate.sql.results.graph.Initializer;
|
import org.hibernate.sql.results.graph.Initializer;
|
||||||
import org.hibernate.sql.results.graph.collection.internal.ArrayInitializer;
|
import org.hibernate.sql.results.graph.collection.internal.ArrayInitializer;
|
||||||
|
@ -169,12 +173,37 @@ public class JdbcValuesSourceProcessingStateStandardImpl implements JdbcValuesSo
|
||||||
|
|
||||||
// now we can finalize loading collections
|
// now we can finalize loading collections
|
||||||
finishLoadingCollections();
|
finishLoadingCollections();
|
||||||
|
|
||||||
|
postLoad();
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
executionContext.getSession().getPersistenceContext().getLoadContexts().deregister( this );
|
executionContext.getSession().getPersistenceContext().getLoadContexts().deregister( this );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void postLoad() {
|
||||||
|
if ( loadingEntityMap == null ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final EventListenerGroup<PostLoadEventListener> listenerGroup = executionContext.getSession().getFactory()
|
||||||
|
.getServiceRegistry()
|
||||||
|
.getService( EventListenerRegistry.class )
|
||||||
|
.getEventListenerGroup( EventType.POST_LOAD );
|
||||||
|
|
||||||
|
loadingEntityMap.forEach(
|
||||||
|
(entityKey, loadingEntityEntry) -> {
|
||||||
|
postLoadEvent.reset();
|
||||||
|
postLoadEvent.setEntity( loadingEntityEntry.getEntityInstance() )
|
||||||
|
.setId( entityKey.getIdentifier() )
|
||||||
|
.setPersister( loadingEntityEntry.getDescriptor() );
|
||||||
|
|
||||||
|
for ( PostLoadEventListener listener : listenerGroup.listeners() ) {
|
||||||
|
listener.onPostLoad( postLoadEvent );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
private void finishLoadingArrays() {
|
private void finishLoadingArrays() {
|
||||||
if ( arrayInitializers != null ) {
|
if ( arrayInitializers != null ) {
|
||||||
for ( CollectionInitializer collectionInitializer : arrayInitializers ) {
|
for ( CollectionInitializer collectionInitializer : arrayInitializers ) {
|
||||||
|
@ -188,7 +217,6 @@ public class JdbcValuesSourceProcessingStateStandardImpl implements JdbcValuesSo
|
||||||
if ( loadingEntityMap == null ) {
|
if ( loadingEntityMap == null ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
log.tracev( "Total objects hydrated: {0}", loadingEntityMap.size() );
|
log.tracev( "Total objects hydrated: {0}", loadingEntityMap.size() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -79,11 +79,11 @@ public class ListResultsConsumer<R> implements ResultsConsumer<List<R>, R> {
|
||||||
rowProcessingState.finishRowProcessing();
|
rowProcessingState.finishRowProcessing();
|
||||||
}
|
}
|
||||||
persistenceContext.initializeNonLazyCollections();
|
persistenceContext.initializeNonLazyCollections();
|
||||||
|
jdbcValuesSourceProcessingState.finishUp( );
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
rowReader.finishUp( jdbcValuesSourceProcessingState );
|
rowReader.finishUp( jdbcValuesSourceProcessingState );
|
||||||
jdbcValuesSourceProcessingState.finishUp();
|
|
||||||
jdbcValues.finishUp( session );
|
jdbcValues.finishUp( session );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,55 +0,0 @@
|
||||||
/*
|
|
||||||
* 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.jpa.test.collection;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import javax.persistence.EntityManager;
|
|
||||||
|
|
||||||
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
|
|
||||||
import org.hibernate.testing.TestForIssue;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
@TestForIssue( jiraKey="HHH-6043" )
|
|
||||||
public class PostLoadTest extends BaseEntityManagerFunctionalTestCase {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Load an entity with a collection of associated entities, that uses a @PostLoad method to
|
|
||||||
* access the association.
|
|
||||||
*/
|
|
||||||
@Test
|
|
||||||
public void testAccessAssociatedSetInPostLoad() {
|
|
||||||
Child child = new Child();
|
|
||||||
child.setId(1);
|
|
||||||
Parent daddy = new Parent();
|
|
||||||
daddy.setId(1);
|
|
||||||
child.setDaddy(daddy);
|
|
||||||
Set<Child> children = new HashSet<Child>();
|
|
||||||
children.add(child);
|
|
||||||
daddy.setChildren(children);
|
|
||||||
|
|
||||||
EntityManager em = getOrCreateEntityManager();
|
|
||||||
|
|
||||||
em.getTransaction().begin();
|
|
||||||
em.persist(daddy);
|
|
||||||
em.getTransaction().commit();
|
|
||||||
em.clear();
|
|
||||||
|
|
||||||
daddy = em.find(Parent.class, 1);
|
|
||||||
assertEquals(1, daddy.getNrOfChildren());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Class<?>[] getAnnotatedClasses() {
|
|
||||||
return new Class[] { Child.class, Parent.class };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
* 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>.
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
*/
|
*/
|
||||||
package org.hibernate.jpa.test.collection;
|
package org.hibernate.orm.test.jpa.collection;
|
||||||
|
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
import javax.persistence.Id;
|
import javax.persistence.Id;
|
||||||
|
@ -27,6 +27,7 @@ public class Child {
|
||||||
public void setId(Integer id) {
|
public void setId(Integer id) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ManyToOne
|
@ManyToOne
|
||||||
public Parent getDaddy() {
|
public Parent getDaddy() {
|
||||||
return daddy;
|
return daddy;
|
|
@ -4,7 +4,7 @@
|
||||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
* 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>.
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
*/
|
*/
|
||||||
package org.hibernate.jpa.test.collection;
|
package org.hibernate.orm.test.jpa.collection;
|
||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
@ -35,6 +35,7 @@ public class Parent {
|
||||||
public void setId(Integer id) {
|
public void setId(Integer id) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
@OneToMany(mappedBy="daddy", fetch=FetchType.EAGER, cascade=CascadeType.ALL)
|
@OneToMany(mappedBy="daddy", fetch=FetchType.EAGER, cascade=CascadeType.ALL)
|
||||||
public Set<Child> getChildren() {
|
public Set<Child> getChildren() {
|
||||||
return children;
|
return children;
|
|
@ -0,0 +1,61 @@
|
||||||
|
/*
|
||||||
|
* 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.orm.test.jpa.collection;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.hibernate.testing.TestForIssue;
|
||||||
|
import org.hibernate.testing.orm.junit.EntityManagerFactoryScope;
|
||||||
|
import org.hibernate.testing.orm.junit.Jpa;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
@TestForIssue(jiraKey = "HHH-6043")
|
||||||
|
@Jpa(
|
||||||
|
annotatedClasses = { Child.class, Parent.class }
|
||||||
|
)
|
||||||
|
public class PostLoadTest {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load an entity with a collection of associated entities, that uses a @PostLoad method to
|
||||||
|
* access the association.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void testAccessAssociatedSetInPostLoad(EntityManagerFactoryScope scope) {
|
||||||
|
scope.inEntityManager(
|
||||||
|
entityManager -> {
|
||||||
|
try {
|
||||||
|
Child child = new Child();
|
||||||
|
child.setId( 1 );
|
||||||
|
Parent daddy = new Parent();
|
||||||
|
daddy.setId( 1 );
|
||||||
|
child.setDaddy( daddy );
|
||||||
|
Set<Child> children = new HashSet<>();
|
||||||
|
children.add( child );
|
||||||
|
daddy.setChildren( children );
|
||||||
|
|
||||||
|
entityManager.getTransaction().begin();
|
||||||
|
entityManager.persist( daddy );
|
||||||
|
entityManager.getTransaction().commit();
|
||||||
|
entityManager.clear();
|
||||||
|
|
||||||
|
daddy = entityManager.find( Parent.class, 1 );
|
||||||
|
assertEquals( 1, daddy.getNrOfChildren() );
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
if ( entityManager.getTransaction().isActive() ) {
|
||||||
|
entityManager.getTransaction().rollback();
|
||||||
|
}
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue