HHH-16913 EntityGraph support for StatelessSession
This commit is contained in:
parent
6b7d5bae3d
commit
294ec27885
|
@ -8,7 +8,10 @@ package org.hibernate;
|
|||
|
||||
import java.io.Closeable;
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
import jakarta.persistence.EntityGraph;
|
||||
import org.hibernate.graph.RootGraph;
|
||||
import org.hibernate.jdbc.ReturningWork;
|
||||
import org.hibernate.jdbc.Work;
|
||||
import org.hibernate.procedure.ProcedureCall;
|
||||
|
@ -240,6 +243,48 @@ public interface SharedSessionContract extends QueryProducer, Closeable, Seriali
|
|||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new mutable {@link EntityGraph} with only a root node.
|
||||
*
|
||||
* @since 6.3
|
||||
*/
|
||||
<T> RootGraph<T> createEntityGraph(Class<T> rootType);
|
||||
|
||||
/**
|
||||
* Create a new mutable copy of the named {@link EntityGraph},
|
||||
* or return {@code null} if there is no graph with the given
|
||||
* name.
|
||||
*
|
||||
* @param graphName the name of the graph
|
||||
*
|
||||
* @see jakarta.persistence.EntityManagerFactory#addNamedEntityGraph(String, EntityGraph)
|
||||
*
|
||||
* @since 6.3
|
||||
*/
|
||||
RootGraph<?> createEntityGraph(String graphName);
|
||||
|
||||
/**
|
||||
* Retrieve the named {@link EntityGraph} as an immutable graph,
|
||||
* or return {@code null} if there is no graph with the given
|
||||
* name.
|
||||
*
|
||||
* @see jakarta.persistence.EntityManagerFactory#addNamedEntityGraph(String, EntityGraph)
|
||||
*
|
||||
* @param graphName the name of the graph
|
||||
*
|
||||
* @since 6.3
|
||||
*/
|
||||
RootGraph<?> getEntityGraph(String graphName);
|
||||
|
||||
/**
|
||||
* Retrieve all named {@link EntityGraph}s with the given type.
|
||||
*
|
||||
* @see jakarta.persistence.EntityManagerFactory#addNamedEntityGraph(String, EntityGraph)
|
||||
*
|
||||
* @since 6.3
|
||||
*/
|
||||
<T> List<EntityGraph<? super T>> getEntityGraphs(Class<T> entityClass);
|
||||
|
||||
/**
|
||||
* The factory which created this session.
|
||||
*/
|
||||
|
|
|
@ -6,6 +6,9 @@
|
|||
*/
|
||||
package org.hibernate;
|
||||
|
||||
import jakarta.persistence.EntityGraph;
|
||||
import org.hibernate.graph.GraphSemantic;
|
||||
|
||||
/**
|
||||
* A command-oriented API often used for performing bulk operations against
|
||||
* the database. A stateless session has no persistence context, and always
|
||||
|
@ -163,6 +166,38 @@ public interface StatelessSession extends SharedSessionContract {
|
|||
*/
|
||||
<T> T get(Class<T> entityClass, Object id, LockMode lockMode);
|
||||
|
||||
/**
|
||||
* Retrieve a row, fetching associations specified by the
|
||||
* given {@link EntityGraph}.
|
||||
*
|
||||
* @param graph The {@link EntityGraph}
|
||||
* @param graphSemantic a {@link GraphSemantic} specifying
|
||||
* how the graph should be interpreted
|
||||
* @param id The id of the entity to retrieve
|
||||
*
|
||||
* @return a detached entity instance
|
||||
*
|
||||
* @since 6.3
|
||||
*/
|
||||
<T> T get(EntityGraph<T> graph, GraphSemantic graphSemantic, Object id);
|
||||
|
||||
/**
|
||||
* Retrieve a row, fetching associations specified by the
|
||||
* given {@link EntityGraph}, and obtaining the specified
|
||||
* lock mode.
|
||||
*
|
||||
* @param graph The {@link EntityGraph}
|
||||
* @param graphSemantic a {@link GraphSemantic} specifying
|
||||
* how the graph should be interpreted
|
||||
* @param id The id of the entity to retrieve
|
||||
* @param lockMode The lock mode to apply to the entity
|
||||
*
|
||||
* @return a detached entity instance
|
||||
*
|
||||
* @since 6.3
|
||||
*/
|
||||
<T> T get(EntityGraph<T> graph, GraphSemantic graphSemantic, Object id, LockMode lockMode);
|
||||
|
||||
/**
|
||||
* Refresh the entity instance state from the database.
|
||||
*
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
*/
|
||||
package org.hibernate.engine.spi;
|
||||
|
||||
import jakarta.persistence.EntityGraph;
|
||||
import jakarta.persistence.FlushModeType;
|
||||
import jakarta.persistence.criteria.CriteriaDelete;
|
||||
import jakarta.persistence.criteria.CriteriaQuery;
|
||||
|
@ -22,6 +23,7 @@ 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.graph.RootGraph;
|
||||
import org.hibernate.jdbc.ReturningWork;
|
||||
import org.hibernate.jdbc.Work;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
|
@ -36,6 +38,7 @@ import org.hibernate.query.sql.spi.NativeQueryImplementor;
|
|||
import org.hibernate.resource.jdbc.spi.JdbcSessionContext;
|
||||
import org.hibernate.resource.transaction.spi.TransactionCoordinator;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.TimeZone;
|
||||
import java.util.UUID;
|
||||
|
@ -593,4 +596,24 @@ public class SharedSessionDelegatorBaseImpl implements SharedSessionContractImpl
|
|||
public TimeZone getJdbcTimeZone() {
|
||||
return delegate.getJdbcTimeZone();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> RootGraph<T> createEntityGraph(Class<T> rootType) {
|
||||
return delegate.createEntityGraph( rootType );
|
||||
}
|
||||
|
||||
@Override
|
||||
public RootGraph<?> createEntityGraph(String graphName) {
|
||||
return delegate.createEntityGraph( graphName );
|
||||
}
|
||||
|
||||
@Override
|
||||
public RootGraph<?> getEntityGraph(String graphName) {
|
||||
return delegate.getEntityGraph( graphName );
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> List<EntityGraph<? super T>> getEntityGraphs(Class<T> entityClass) {
|
||||
return delegate.getEntityGraphs( entityClass );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,7 +32,6 @@ import org.hibernate.loader.ast.spi.CascadingFetchProfile;
|
|||
import org.hibernate.metamodel.spi.MappingMetamodelImplementor;
|
||||
import org.hibernate.persister.collection.CollectionPersister;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.pretty.MessageHelper;
|
||||
import org.hibernate.type.CollectionType;
|
||||
import org.hibernate.type.CompositeType;
|
||||
import org.hibernate.type.Type;
|
||||
|
|
|
@ -17,6 +17,7 @@ import java.util.TimeZone;
|
|||
import java.util.UUID;
|
||||
import java.util.function.Function;
|
||||
|
||||
import jakarta.persistence.EntityGraph;
|
||||
import org.hibernate.CacheMode;
|
||||
import org.hibernate.EntityNameResolver;
|
||||
import org.hibernate.FlushMode;
|
||||
|
@ -41,6 +42,8 @@ import org.hibernate.engine.spi.SessionFactoryImplementor;
|
|||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.engine.transaction.internal.TransactionImpl;
|
||||
import org.hibernate.engine.transaction.spi.TransactionImplementor;
|
||||
import org.hibernate.graph.internal.RootGraphImpl;
|
||||
import org.hibernate.graph.spi.RootGraphImplementor;
|
||||
import org.hibernate.id.uuid.StandardRandomStrategy;
|
||||
import org.hibernate.jdbc.ReturningWork;
|
||||
import org.hibernate.jdbc.Work;
|
||||
|
@ -1373,6 +1376,38 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont
|
|||
return query;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> RootGraphImplementor<T> createEntityGraph(Class<T> rootType) {
|
||||
checkOpen();
|
||||
return new RootGraphImpl<>( null, getFactory().getJpaMetamodel().entity( rootType ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public RootGraphImplementor<?> createEntityGraph(String graphName) {
|
||||
checkOpen();
|
||||
final RootGraphImplementor<?> named = getFactory().findEntityGraphByName( graphName );
|
||||
if ( named == null ) {
|
||||
return null;
|
||||
}
|
||||
return named.makeRootGraph( graphName, true );
|
||||
}
|
||||
|
||||
@Override
|
||||
public RootGraphImplementor<?> getEntityGraph(String graphName) {
|
||||
checkOpen();
|
||||
final RootGraphImplementor<?> named = getFactory().findEntityGraphByName( graphName );
|
||||
if ( named == null ) {
|
||||
throw new IllegalArgumentException( "Could not locate EntityGraph with given name : " + graphName );
|
||||
}
|
||||
return named;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> List<EntityGraph<? super T>> getEntityGraphs(Class<T> entityClass) {
|
||||
checkOpen();
|
||||
return getFactory().findEntityGraphsByType( entityClass );
|
||||
}
|
||||
|
||||
private void writeObject(ObjectOutputStream oos) throws IOException {
|
||||
if ( log.isTraceEnabled() ) {
|
||||
log.trace( "Serializing " + getClass().getSimpleName() + " [" );
|
||||
|
|
|
@ -2860,38 +2860,6 @@ public class SessionImpl
|
|||
return getFactory().getJpaMetamodel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> RootGraphImplementor<T> createEntityGraph(Class<T> rootType) {
|
||||
checkOpen();
|
||||
return new RootGraphImpl<>( null, getFactory().getJpaMetamodel().entity( rootType ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public RootGraphImplementor<?> createEntityGraph(String graphName) {
|
||||
checkOpen();
|
||||
final RootGraphImplementor<?> named = getEntityManagerFactory().findEntityGraphByName( graphName );
|
||||
if ( named == null ) {
|
||||
return null;
|
||||
}
|
||||
return named.makeRootGraph( graphName, true );
|
||||
}
|
||||
|
||||
@Override
|
||||
public RootGraphImplementor<?> getEntityGraph(String graphName) {
|
||||
checkOpen();
|
||||
final RootGraphImplementor<?> named = getEntityManagerFactory().findEntityGraphByName( graphName );
|
||||
if ( named == null ) {
|
||||
throw new IllegalArgumentException( "Could not locate EntityGraph with given name : " + graphName );
|
||||
}
|
||||
return named;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> List<EntityGraph<? super T>> getEntityGraphs(Class<T> entityClass) {
|
||||
checkOpen();
|
||||
return getEntityManagerFactory().findEntityGraphsByType( entityClass );
|
||||
}
|
||||
|
||||
/**
|
||||
* Used by JDK serialization...
|
||||
*
|
||||
|
|
|
@ -8,6 +8,7 @@ package org.hibernate.internal;
|
|||
|
||||
import java.util.Set;
|
||||
|
||||
import jakarta.persistence.EntityGraph;
|
||||
import org.hibernate.CacheMode;
|
||||
import org.hibernate.FlushMode;
|
||||
import org.hibernate.HibernateException;
|
||||
|
@ -21,6 +22,7 @@ import org.hibernate.bytecode.spi.BytecodeEnhancementMetadata;
|
|||
import org.hibernate.cache.spi.access.EntityDataAccess;
|
||||
import org.hibernate.collection.spi.PersistentCollection;
|
||||
import org.hibernate.engine.internal.StatefulPersistenceContext;
|
||||
import org.hibernate.engine.spi.EffectiveEntityGraph;
|
||||
import org.hibernate.engine.spi.EntityKey;
|
||||
import org.hibernate.engine.spi.LoadQueryInfluencers;
|
||||
import org.hibernate.engine.spi.PersistenceContext;
|
||||
|
@ -28,6 +30,9 @@ import org.hibernate.engine.spi.PersistentAttributeInterceptable;
|
|||
import org.hibernate.engine.spi.PersistentAttributeInterceptor;
|
||||
import org.hibernate.engine.transaction.internal.jta.JtaStatusHelper;
|
||||
import org.hibernate.engine.transaction.jta.platform.spi.JtaPlatform;
|
||||
import org.hibernate.graph.GraphSemantic;
|
||||
import org.hibernate.graph.spi.RootGraphImplementor;
|
||||
import org.hibernate.loader.ast.spi.CascadingFetchProfile;
|
||||
import org.hibernate.persister.collection.CollectionPersister;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.proxy.LazyInitializer;
|
||||
|
@ -63,24 +68,15 @@ import static org.hibernate.proxy.HibernateProxy.extractLazyInitializer;
|
|||
public class StatelessSessionImpl extends AbstractSharedSessionContract implements StatelessSession {
|
||||
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( StatelessSessionImpl.class );
|
||||
|
||||
private static final LoadQueryInfluencers NO_INFLUENCERS = new LoadQueryInfluencers() {
|
||||
@Override @Deprecated
|
||||
public String getInternalFetchProfile() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override @Deprecated
|
||||
public void setInternalFetchProfile(String internalFetchProfile) {
|
||||
}
|
||||
};
|
||||
|
||||
private final PersistenceContext temporaryPersistenceContext = new StatefulPersistenceContext( this );
|
||||
|
||||
private final LoadQueryInfluencers influencers;
|
||||
private final PersistenceContext temporaryPersistenceContext;
|
||||
private final boolean connectionProvided;
|
||||
|
||||
public StatelessSessionImpl(SessionFactoryImpl factory, SessionCreationOptions options) {
|
||||
super( factory, options );
|
||||
connectionProvided = options.getConnection() != null;
|
||||
temporaryPersistenceContext = new StatefulPersistenceContext( this );
|
||||
influencers = new LoadQueryInfluencers( getFactory() );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -238,6 +234,30 @@ public class StatelessSessionImpl extends AbstractSharedSessionContract implemen
|
|||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T get(EntityGraph<T> graph, GraphSemantic graphSemantic, Object id) {
|
||||
return get( graph, graphSemantic, id, LockMode.NONE );
|
||||
}
|
||||
|
||||
@Override @SuppressWarnings("unchecked")
|
||||
public <T> T get(
|
||||
EntityGraph<T> graph, GraphSemantic graphSemantic,
|
||||
Object id, LockMode lockMode) {
|
||||
final RootGraphImplementor<T> rootGraph = (RootGraphImplementor<T>) graph;
|
||||
checkOpen();
|
||||
|
||||
final EffectiveEntityGraph effectiveEntityGraph =
|
||||
getLoadQueryInfluencers().getEffectiveEntityGraph();
|
||||
effectiveEntityGraph.applyGraph( rootGraph, graphSemantic );
|
||||
|
||||
try {
|
||||
return (T) get( rootGraph.getGraphedType().getTypeName(), id, lockMode );
|
||||
}
|
||||
finally {
|
||||
effectiveEntityGraph.clear();
|
||||
}
|
||||
}
|
||||
|
||||
private EntityPersister getEntityPersister(String entityName) {
|
||||
return getFactory().getMappingMetamodel().getEntityDescriptor( entityName );
|
||||
}
|
||||
|
@ -278,15 +298,10 @@ public class StatelessSessionImpl extends AbstractSharedSessionContract implemen
|
|||
}
|
||||
}
|
||||
|
||||
final String previousFetchProfile = getLoadQueryInfluencers().getInternalFetchProfile();
|
||||
Object result;
|
||||
try {
|
||||
getLoadQueryInfluencers().setInternalFetchProfile( "refresh" );
|
||||
result = persister.load( id, entity, getNullSafeLockMode( lockMode ), this );
|
||||
}
|
||||
finally {
|
||||
getLoadQueryInfluencers().setInternalFetchProfile( previousFetchProfile );
|
||||
}
|
||||
final Object result = getLoadQueryInfluencers().fromInternalFetchProfile(
|
||||
CascadingFetchProfile.REFRESH,
|
||||
() -> persister.load( id, entity, getNullSafeLockMode( lockMode ), this )
|
||||
);
|
||||
UnresolvableObjectException.throwIfNull( result, id, persister.getEntityName() );
|
||||
if ( temporaryPersistenceContext.isLoadFinished() ) {
|
||||
temporaryPersistenceContext.clear();
|
||||
|
@ -619,7 +634,7 @@ public class StatelessSessionImpl extends AbstractSharedSessionContract implemen
|
|||
|
||||
@Override
|
||||
public LoadQueryInfluencers getLoadQueryInfluencers() {
|
||||
return NO_INFLUENCERS;
|
||||
return influencers;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
Loading…
Reference in New Issue