HHH-17953 fix StatelessSession.fetch() for empty collection

Signed-off-by: Gavin King <gavin@hibernate.org>
This commit is contained in:
Gavin King 2024-04-13 11:48:58 +02:00
parent c0d2075ee6
commit 6695617210
3 changed files with 38 additions and 8 deletions

View File

@ -20,7 +20,6 @@ import org.hibernate.event.spi.InitializeCollectionEventListener;
import org.hibernate.internal.CoreLogging; import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.pretty.MessageHelper;
import org.hibernate.sql.results.internal.ResultsHelper; import org.hibernate.sql.results.internal.ResultsHelper;
import org.hibernate.stat.spi.StatisticsImplementor; import org.hibernate.stat.spi.StatisticsImplementor;
@ -39,7 +38,8 @@ public class DefaultInitializeCollectionEventListener implements InitializeColle
final PersistentCollection<?> collection = event.getCollection(); final PersistentCollection<?> collection = event.getCollection();
final SessionImplementor source = event.getSession(); final SessionImplementor source = event.getSession();
final CollectionEntry ce = source.getPersistenceContextInternal().getCollectionEntry( collection ); final PersistenceContext persistenceContext = source.getPersistenceContextInternal();
final CollectionEntry ce = persistenceContext.getCollectionEntry( collection );
if ( ce == null ) { if ( ce == null ) {
throw new HibernateException( "collection was evicted" ); throw new HibernateException( "collection was evicted" );
} }
@ -65,7 +65,7 @@ public class DefaultInitializeCollectionEventListener implements InitializeColle
LOG.trace( "Collection not cached" ); LOG.trace( "Collection not cached" );
} }
loadedPersister.initialize( loadedKey, source ); loadedPersister.initialize( loadedKey, source );
handlePotentiallyEmptyCollection( collection, source, ce, loadedPersister ); handlePotentiallyEmptyCollection( collection, persistenceContext, loadedKey, loadedPersister );
if ( LOG.isTraceEnabled() ) { if ( LOG.isTraceEnabled() ) {
LOG.trace( "Collection initialized" ); LOG.trace( "Collection initialized" );
} }
@ -78,18 +78,18 @@ public class DefaultInitializeCollectionEventListener implements InitializeColle
} }
} }
private void handlePotentiallyEmptyCollection( public static void handlePotentiallyEmptyCollection(
PersistentCollection<?> collection, PersistentCollection<?> collection,
SessionImplementor source, PersistenceContext persistenceContext,
CollectionEntry ce, Object loadedKey,
CollectionPersister loadedPersister) { CollectionPersister loadedPersister) {
if ( !collection.wasInitialized() ) { if ( !collection.wasInitialized() ) {
collection.initializeEmptyCollection( loadedPersister ); collection.initializeEmptyCollection( loadedPersister );
ResultsHelper.finalizeCollectionLoading( ResultsHelper.finalizeCollectionLoading(
source.getPersistenceContext(), persistenceContext,
loadedPersister, loadedPersister,
collection, collection,
ce.getLoadedKey(), loadedKey,
true true
); );
} }

View File

@ -49,6 +49,7 @@ import static org.hibernate.engine.internal.ManagedTypeHelper.isPersistentAttrib
import static org.hibernate.engine.internal.Versioning.incrementVersion; import static org.hibernate.engine.internal.Versioning.incrementVersion;
import static org.hibernate.engine.internal.Versioning.seedVersion; import static org.hibernate.engine.internal.Versioning.seedVersion;
import static org.hibernate.engine.internal.Versioning.setVersion; import static org.hibernate.engine.internal.Versioning.setVersion;
import static org.hibernate.event.internal.DefaultInitializeCollectionEventListener.handlePotentiallyEmptyCollection;
import static org.hibernate.generator.EventType.INSERT; import static org.hibernate.generator.EventType.INSERT;
import static org.hibernate.internal.util.NullnessUtil.castNonNull; import static org.hibernate.internal.util.NullnessUtil.castNonNull;
import static org.hibernate.pretty.MessageHelper.infoString; import static org.hibernate.pretty.MessageHelper.infoString;
@ -503,6 +504,8 @@ public class StatelessSessionImpl extends AbstractSharedSessionContract implemen
persistentCollection.setCurrentSession( this ); persistentCollection.setCurrentSession( this );
try { try {
collectionDescriptor.initialize( key, this ); collectionDescriptor.initialize( key, this );
handlePotentiallyEmptyCollection( persistentCollection, getPersistenceContextInternal(), key,
collectionDescriptor );
} }
finally { finally {
persistentCollection.unsetSession( this ); persistentCollection.unsetSession( this );

View File

@ -89,6 +89,33 @@ public class FetchTest extends BaseNonConfigCoreFunctionalTestCase {
long count = stats.getPrepareStatementCount(); long count = stats.getPrepareStatementCount();
session.fetch( school.students); session.fetch( school.students);
assertTrue( Hibernate.isInitialized( school.students) ); assertTrue( Hibernate.isInitialized( school.students) );
assertEquals( 1, school.students.size() );
assertEquals( count+1, stats.getPrepareStatementCount() );
}
);
}
@Test
public void testFetchEmpty() {
inStatelessTransaction(
session -> {
Secondary secondary = new Secondary( "BHS" );
session.insert(secondary);
}
);
inStatelessSession(
session -> {
final Statistics stats = sessionFactory().getStatistics();
stats.clear();
final School school = session.get( School.class, "BHS" );
assertFalse( Hibernate.isInitialized( school.students) );
assertTrue( school.students instanceof PersistentSet );
long count = stats.getPrepareStatementCount();
session.fetch( school.students);
assertTrue( Hibernate.isInitialized( school.students) );
assertTrue( school.students.isEmpty() );
assertEquals( count+1, stats.getPrepareStatementCount() ); assertEquals( count+1, stats.getPrepareStatementCount() );
} }