HHH-17966 EAGER collections in StatelessSession (#8186)
This commit is contained in:
parent
431cf992ec
commit
7e108433ea
|
@ -26,7 +26,6 @@ import org.hibernate.engine.jdbc.LobCreator;
|
|||
import org.hibernate.engine.jdbc.connections.spi.JdbcConnectionAccess;
|
||||
import org.hibernate.engine.jdbc.spi.JdbcCoordinator;
|
||||
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
||||
import org.hibernate.event.spi.AutoFlushEvent;
|
||||
import org.hibernate.event.spi.EventManager;
|
||||
import org.hibernate.graph.RootGraph;
|
||||
import org.hibernate.jdbc.ReturningWork;
|
||||
|
|
|
@ -48,7 +48,7 @@ public abstract class AbstractCollectionEvent extends AbstractEvent {
|
|||
|
||||
protected static CollectionPersister getLoadedCollectionPersister( PersistentCollection<?> collection, EventSource source ) {
|
||||
CollectionEntry ce = source.getPersistenceContextInternal().getCollectionEntry( collection );
|
||||
return ( ce == null ? null : ce.getLoadedPersister() );
|
||||
return ce == null ? null : ce.getLoadedPersister();
|
||||
}
|
||||
|
||||
protected static Object getLoadedOwnerOrNull( PersistentCollection<?> collection, EventSource source ) {
|
||||
|
@ -68,19 +68,24 @@ public abstract class AbstractCollectionEvent extends AbstractEvent {
|
|||
CollectionPersister collectionPersister,
|
||||
Object affectedOwner,
|
||||
EventSource source ) {
|
||||
|
||||
// collectionPersister should not be null, but we don't want to throw
|
||||
// an exception if it is null
|
||||
String entityName = collectionPersister == null
|
||||
? null
|
||||
: collectionPersister.getOwnerEntityPersister().getEntityName();
|
||||
if ( affectedOwner != null ) {
|
||||
EntityEntry ee = source.getPersistenceContextInternal().getEntry( affectedOwner );
|
||||
if ( ee != null && ee.getEntityName() != null) {
|
||||
entityName = ee.getEntityName();
|
||||
final EntityEntry entry =
|
||||
source.getPersistenceContextInternal()
|
||||
.getEntry( affectedOwner );
|
||||
if ( entry != null && entry.getEntityName() != null ) {
|
||||
return entry.getEntityName();
|
||||
}
|
||||
}
|
||||
return entityName;
|
||||
}
|
||||
|
||||
if ( collectionPersister != null ) {
|
||||
return collectionPersister.getOwnerEntityPersister().getEntityName();
|
||||
}
|
||||
else {
|
||||
// collectionPersister should not be null,
|
||||
// but we don't want to throw an exception
|
||||
// if it is null
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public PersistentCollection<?> getCollection() {
|
||||
|
|
|
@ -23,6 +23,7 @@ import org.hibernate.cache.spi.access.EntityDataAccess;
|
|||
import org.hibernate.collection.spi.CollectionSemantics;
|
||||
import org.hibernate.collection.spi.PersistentCollection;
|
||||
import org.hibernate.engine.internal.StatefulPersistenceContext;
|
||||
import org.hibernate.engine.spi.CollectionEntry;
|
||||
import org.hibernate.engine.spi.EffectiveEntityGraph;
|
||||
import org.hibernate.engine.spi.EntityHolder;
|
||||
import org.hibernate.engine.spi.EntityKey;
|
||||
|
@ -71,6 +72,7 @@ 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.collectionInfoString;
|
||||
import static org.hibernate.pretty.MessageHelper.infoString;
|
||||
import static org.hibernate.proxy.HibernateProxy.extractLazyInitializer;
|
||||
|
||||
|
@ -529,16 +531,35 @@ public class StatelessSessionImpl extends AbstractSharedSessionContract implemen
|
|||
}
|
||||
|
||||
@Override
|
||||
public void initializeCollection(
|
||||
PersistentCollection<?> collection,
|
||||
boolean writing) throws HibernateException {
|
||||
throw new SessionException( "collections cannot be fetched by a stateless session" );
|
||||
public void initializeCollection(PersistentCollection<?> collection, boolean writing)
|
||||
throws HibernateException {
|
||||
final PersistenceContext persistenceContext = getPersistenceContextInternal();
|
||||
final CollectionEntry ce = persistenceContext.getCollectionEntry( collection );
|
||||
if ( ce == null ) {
|
||||
throw new HibernateException( "no entry for collection" );
|
||||
}
|
||||
if ( !collection.wasInitialized() ) {
|
||||
final CollectionPersister loadedPersister = ce.getLoadedPersister();
|
||||
final Object loadedKey = ce.getLoadedKey();
|
||||
if ( LOG.isTraceEnabled() ) {
|
||||
LOG.tracev( "Initializing collection {0}",
|
||||
collectionInfoString( loadedPersister, collection, loadedKey, this ) );
|
||||
}
|
||||
loadedPersister.initialize( loadedKey, this );
|
||||
handlePotentiallyEmptyCollection( collection, persistenceContext, loadedKey, loadedPersister );
|
||||
if ( LOG.isTraceEnabled() ) {
|
||||
LOG.trace( "Collection initialized" );
|
||||
}
|
||||
//TODO: statistics!
|
||||
// final StatisticsImplementor statistics = getFactory().getStatistics();
|
||||
// if ( statistics.isStatisticsEnabled() ) {
|
||||
// statistics.fetchCollection( loadedPersister.getRole() );
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object instantiate(
|
||||
String entityName,
|
||||
Object id) throws HibernateException {
|
||||
public Object instantiate(String entityName, Object id) throws HibernateException {
|
||||
return instantiate( getEntityPersister( entityName ), id );
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
package org.hibernate.orm.test.stateless;
|
||||
|
||||
import jakarta.persistence.ElementCollection;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.Id;
|
||||
import org.hibernate.Hibernate;
|
||||
import org.hibernate.testing.orm.junit.DomainModel;
|
||||
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import static jakarta.persistence.FetchType.EAGER;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
@SessionFactory
|
||||
@DomainModel(annotatedClasses = EagerCollectionInStatelessTest.WithEagerCollection.class)
|
||||
public class EagerCollectionInStatelessTest {
|
||||
@Test
|
||||
void test(SessionFactoryScope scope) {
|
||||
scope.inStatelessTransaction(s-> {
|
||||
WithEagerCollection entity = new WithEagerCollection();
|
||||
entity.eager.add("Hello");
|
||||
entity.eager.add("World");
|
||||
entity.lazy.add("Goodbye");
|
||||
entity.lazy.add("World");
|
||||
s.insert(entity);
|
||||
});
|
||||
scope.inStatelessSession(s-> {
|
||||
WithEagerCollection entity = s.get(WithEagerCollection.class, 69L);
|
||||
assertTrue(Hibernate.isInitialized(entity.eager));
|
||||
assertFalse(Hibernate.isInitialized(entity.lazy));
|
||||
s.fetch(entity.lazy);
|
||||
assertTrue(Hibernate.isInitialized(entity.lazy));
|
||||
assertEquals(2, entity.eager.size());
|
||||
assertEquals(2, entity.lazy.size());
|
||||
});
|
||||
scope.inStatelessSession(s-> {
|
||||
WithEagerCollection entity =
|
||||
s.createSelectionQuery("where id= 69L", WithEagerCollection.class)
|
||||
.getSingleResult();
|
||||
assertTrue(Hibernate.isInitialized(entity.eager));
|
||||
assertFalse(Hibernate.isInitialized(entity.lazy));
|
||||
s.fetch(entity.lazy);
|
||||
assertTrue(Hibernate.isInitialized(entity.lazy));
|
||||
assertEquals(2, entity.eager.size());
|
||||
assertEquals(2, entity.lazy.size());
|
||||
});
|
||||
}
|
||||
|
||||
@Entity
|
||||
static class WithEagerCollection {
|
||||
@Id long id = 69L;
|
||||
@ElementCollection(fetch = EAGER)
|
||||
Set<String> eager = new HashSet<>();
|
||||
@ElementCollection
|
||||
Set<String> lazy = new HashSet<>();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue