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 18c0fd7a78
commit 082e47efb7
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.CoreMessageLogger;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.pretty.MessageHelper;
import org.hibernate.sql.results.internal.ResultsHelper;
import org.hibernate.stat.spi.StatisticsImplementor;
@ -39,7 +38,8 @@ public class DefaultInitializeCollectionEventListener implements InitializeColle
final PersistentCollection<?> collection = event.getCollection();
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 ) {
throw new HibernateException( "collection was evicted" );
}
@ -65,7 +65,7 @@ public class DefaultInitializeCollectionEventListener implements InitializeColle
LOG.trace( "Collection not cached" );
}
loadedPersister.initialize( loadedKey, source );
handlePotentiallyEmptyCollection( collection, source, ce, loadedPersister );
handlePotentiallyEmptyCollection( collection, persistenceContext, loadedKey, loadedPersister );
if ( LOG.isTraceEnabled() ) {
LOG.trace( "Collection initialized" );
}
@ -78,18 +78,18 @@ public class DefaultInitializeCollectionEventListener implements InitializeColle
}
}
private void handlePotentiallyEmptyCollection(
public static void handlePotentiallyEmptyCollection(
PersistentCollection<?> collection,
SessionImplementor source,
CollectionEntry ce,
PersistenceContext persistenceContext,
Object loadedKey,
CollectionPersister loadedPersister) {
if ( !collection.wasInitialized() ) {
collection.initializeEmptyCollection( loadedPersister );
ResultsHelper.finalizeCollectionLoading(
source.getPersistenceContext(),
persistenceContext,
loadedPersister,
collection,
ce.getLoadedKey(),
loadedKey,
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.seedVersion;
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.internal.util.NullnessUtil.castNonNull;
import static org.hibernate.pretty.MessageHelper.infoString;
@ -503,6 +504,8 @@ public class StatelessSessionImpl extends AbstractSharedSessionContract implemen
persistentCollection.setCurrentSession( this );
try {
collectionDescriptor.initialize( key, this );
handlePotentiallyEmptyCollection( persistentCollection, getPersistenceContextInternal(), key,
collectionDescriptor );
}
finally {
persistentCollection.unsetSession( this );

View File

@ -89,6 +89,33 @@ public class FetchTest extends BaseNonConfigCoreFunctionalTestCase {
long count = stats.getPrepareStatementCount();
session.fetch( 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() );
}