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.connections.spi.JdbcConnectionAccess;
|
||||||
import org.hibernate.engine.jdbc.spi.JdbcCoordinator;
|
import org.hibernate.engine.jdbc.spi.JdbcCoordinator;
|
||||||
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
||||||
import org.hibernate.event.spi.AutoFlushEvent;
|
|
||||||
import org.hibernate.event.spi.EventManager;
|
import org.hibernate.event.spi.EventManager;
|
||||||
import org.hibernate.graph.RootGraph;
|
import org.hibernate.graph.RootGraph;
|
||||||
import org.hibernate.jdbc.ReturningWork;
|
import org.hibernate.jdbc.ReturningWork;
|
||||||
|
|
|
@ -48,7 +48,7 @@ public abstract class AbstractCollectionEvent extends AbstractEvent {
|
||||||
|
|
||||||
protected static CollectionPersister getLoadedCollectionPersister( PersistentCollection<?> collection, EventSource source ) {
|
protected static CollectionPersister getLoadedCollectionPersister( PersistentCollection<?> collection, EventSource source ) {
|
||||||
CollectionEntry ce = source.getPersistenceContextInternal().getCollectionEntry( collection );
|
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 ) {
|
protected static Object getLoadedOwnerOrNull( PersistentCollection<?> collection, EventSource source ) {
|
||||||
|
@ -68,19 +68,24 @@ public abstract class AbstractCollectionEvent extends AbstractEvent {
|
||||||
CollectionPersister collectionPersister,
|
CollectionPersister collectionPersister,
|
||||||
Object affectedOwner,
|
Object affectedOwner,
|
||||||
EventSource source ) {
|
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 ) {
|
if ( affectedOwner != null ) {
|
||||||
EntityEntry ee = source.getPersistenceContextInternal().getEntry( affectedOwner );
|
final EntityEntry entry =
|
||||||
if ( ee != null && ee.getEntityName() != null) {
|
source.getPersistenceContextInternal()
|
||||||
entityName = ee.getEntityName();
|
.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() {
|
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.CollectionSemantics;
|
||||||
import org.hibernate.collection.spi.PersistentCollection;
|
import org.hibernate.collection.spi.PersistentCollection;
|
||||||
import org.hibernate.engine.internal.StatefulPersistenceContext;
|
import org.hibernate.engine.internal.StatefulPersistenceContext;
|
||||||
|
import org.hibernate.engine.spi.CollectionEntry;
|
||||||
import org.hibernate.engine.spi.EffectiveEntityGraph;
|
import org.hibernate.engine.spi.EffectiveEntityGraph;
|
||||||
import org.hibernate.engine.spi.EntityHolder;
|
import org.hibernate.engine.spi.EntityHolder;
|
||||||
import org.hibernate.engine.spi.EntityKey;
|
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.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.collectionInfoString;
|
||||||
import static org.hibernate.pretty.MessageHelper.infoString;
|
import static org.hibernate.pretty.MessageHelper.infoString;
|
||||||
import static org.hibernate.proxy.HibernateProxy.extractLazyInitializer;
|
import static org.hibernate.proxy.HibernateProxy.extractLazyInitializer;
|
||||||
|
|
||||||
|
@ -529,16 +531,35 @@ public class StatelessSessionImpl extends AbstractSharedSessionContract implemen
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initializeCollection(
|
public void initializeCollection(PersistentCollection<?> collection, boolean writing)
|
||||||
PersistentCollection<?> collection,
|
throws HibernateException {
|
||||||
boolean writing) throws HibernateException {
|
final PersistenceContext persistenceContext = getPersistenceContextInternal();
|
||||||
throw new SessionException( "collections cannot be fetched by a stateless session" );
|
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
|
@Override
|
||||||
public Object instantiate(
|
public Object instantiate(String entityName, Object id) throws HibernateException {
|
||||||
String entityName,
|
|
||||||
Object id) throws HibernateException {
|
|
||||||
return instantiate( getEntityPersister( entityName ), id );
|
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