All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.hibernate.internal.StatelessSessionImpl Maven / Gradle / Ivy

There is a newer version: 6.6.2.Final
Show newest version
/*
 * Hibernate, Relational Persistence for Idiomatic Java
 *
 * License: GNU Lesser General Public License (LGPL), version 2.1 or later.
 * See the lgpl.txt file in the root directory or .
 */
package org.hibernate.internal;

import java.util.Set;
import java.util.function.BiConsumer;

import org.hibernate.CacheMode;
import org.hibernate.FlushMode;
import org.hibernate.HibernateException;
import org.hibernate.LockMode;
import org.hibernate.SessionException;
import org.hibernate.StatelessSession;
import org.hibernate.TransientObjectException;
import org.hibernate.UnresolvableObjectException;
import org.hibernate.bytecode.enhance.spi.interceptor.EnhancementAsProxyLazinessInterceptor;
import org.hibernate.bytecode.spi.BytecodeEnhancementMetadata;
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;
import org.hibernate.engine.spi.LoadQueryInfluencers;
import org.hibernate.engine.spi.PersistenceContext;
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.event.spi.PostDeleteEvent;
import org.hibernate.event.spi.PostDeleteEventListener;
import org.hibernate.event.spi.PostInsertEvent;
import org.hibernate.event.spi.PostInsertEventListener;
import org.hibernate.event.spi.PostUpdateEvent;
import org.hibernate.event.spi.PostUpdateEventListener;
import org.hibernate.event.spi.PostUpsertEvent;
import org.hibernate.event.spi.PostUpsertEventListener;
import org.hibernate.event.spi.PreDeleteEvent;
import org.hibernate.event.spi.PreDeleteEventListener;
import org.hibernate.event.spi.PreInsertEvent;
import org.hibernate.event.spi.PreInsertEventListener;
import org.hibernate.event.spi.PreUpdateEvent;
import org.hibernate.event.spi.PreUpdateEventListener;
import org.hibernate.event.spi.PreUpsertEvent;
import org.hibernate.event.spi.PreUpsertEventListener;
import org.hibernate.generator.BeforeExecutionGenerator;
import org.hibernate.generator.Generator;
import org.hibernate.generator.values.GeneratedValues;
import org.hibernate.graph.GraphSemantic;
import org.hibernate.graph.spi.RootGraphImplementor;
import org.hibernate.loader.ast.spi.CascadingFetchProfile;
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.proxy.LazyInitializer;
import org.hibernate.stat.spi.StatisticsImplementor;
import org.hibernate.tuple.entity.EntityMetamodel;

import jakarta.persistence.EntityGraph;
import jakarta.transaction.SystemException;

import static org.hibernate.engine.internal.ManagedTypeHelper.asPersistentAttributeInterceptable;
import static org.hibernate.engine.internal.ManagedTypeHelper.isPersistentAttributeInterceptable;
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.collectionInfoString;
import static org.hibernate.pretty.MessageHelper.infoString;
import static org.hibernate.proxy.HibernateProxy.extractLazyInitializer;

/**
 * Concrete implementation of the {@link StatelessSession} API.
 * 

* Exposes two interfaces: *

    *
  • {@link StatelessSession} to the application, and *
  • {@link org.hibernate.engine.spi.SharedSessionContractImplementor} (an SPI interface) to other subsystems. *
*

* This class is not thread-safe. * * @author Gavin King * @author Steve Ebersole */ public class StatelessSessionImpl extends AbstractSharedSessionContract implements StatelessSession { private static final CoreMessageLogger LOG = CoreLogging.messageLogger( StatelessSessionImpl.class ); 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() ); setUpMultitenancy( factory, influencers ); } @Override public boolean shouldAutoJoinTransaction() { return true; } // inserts ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @Override public Object insert(Object entity) { return insert( null, entity ); } @Override public Object insert(String entityName, Object entity) { checkOpen(); final EntityPersister persister = getEntityPersister( entityName, entity ); final Object id; final Object[] state = persister.getValues( entity ); if ( persister.isVersioned() ) { if ( seedVersion( entity, state, persister, this ) ) { persister.setValues( entity, state ); } } final Generator generator = persister.getGenerator(); if ( !generator.generatedOnExecution( entity, this ) ) { id = ( (BeforeExecutionGenerator) generator).generate( this, entity, null, INSERT ); if ( firePreInsert(entity, id, state, persister) ) { return id; } getInterceptor() .onInsert( entity, id, state, persister.getPropertyNames(), persister.getPropertyTypes() ); persister.getInsertCoordinator().insert( entity, id, state, this ); } else { if ( firePreInsert(entity, null, state, persister) ) { return null; } getInterceptor() .onInsert( entity, null, state, persister.getPropertyNames(), persister.getPropertyTypes() ); final GeneratedValues generatedValues = persister.getInsertCoordinator().insert( entity, state, this ); id = castNonNull( generatedValues ).getGeneratedValue( persister.getIdentifierMapping() ); } persister.setIdentifier( entity, id, this ); forEachOwnedCollection( entity, id, persister, (descriptor, collection) -> { descriptor.recreate( collection, id, this); final StatisticsImplementor statistics = getFactory().getStatistics(); if ( statistics.isStatisticsEnabled() ) { statistics.recreateCollection( descriptor.getRole() ); } } ); firePostInsert(entity, id, state, persister); final StatisticsImplementor statistics = getFactory().getStatistics(); if ( statistics.isStatisticsEnabled() ) { statistics.insertEntity( persister.getEntityName() ); } return id; } // deletes ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @Override public void delete(Object entity) { delete( null, entity ); } @Override public void delete(String entityName, Object entity) { checkOpen(); final EntityPersister persister = getEntityPersister( entityName, entity ); final Object id = persister.getIdentifier( entity, this ); final Object version = persister.getVersion( entity ); if ( !firePreDelete(entity, id, persister) ) { getInterceptor() .onDelete( entity, id, persister.getPropertyNames(), persister.getPropertyTypes() ); forEachOwnedCollection( entity, id, persister, (descriptor, collection) -> { descriptor.remove( id, this ); final StatisticsImplementor statistics = getFactory().getStatistics(); if ( statistics.isStatisticsEnabled() ) { statistics.removeCollection( descriptor.getRole() ); } } ); persister.getDeleteCoordinator().delete( entity, id, version, this ); firePostDelete(entity, id, persister); final StatisticsImplementor statistics = getFactory().getStatistics(); if ( statistics.isStatisticsEnabled() ) { statistics.deleteEntity( persister.getEntityName() ); } } } // updates ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @Override public void update(Object entity) { update( null, entity ); } @Override public void upsert(Object entity) { upsert( null, entity ); } @Override public void update(String entityName, Object entity) { checkOpen(); final EntityPersister persister = getEntityPersister( entityName, entity ); final Object id = persister.getIdentifier( entity, this ); final Object[] state = persister.getValues( entity ); final Object oldVersion; if ( persister.isVersioned() ) { oldVersion = persister.getVersion( entity ); final Object newVersion = incrementVersion( entity, oldVersion, persister, this ); setVersion( state, newVersion, persister ); persister.setValues( entity, state ); } else { oldVersion = null; } if ( !firePreUpdate(entity, id, state, persister) ) { getInterceptor() .onUpdate( entity, id, state, persister.getPropertyNames(), persister.getPropertyTypes() ); persister.getUpdateCoordinator().update( entity, id, null, state, oldVersion, null, null, false, this ); forEachOwnedCollection( entity, id, persister, (descriptor, collection) -> { // TODO: can we do better here? descriptor.remove( id, this ); descriptor.recreate( collection, id, this ); final StatisticsImplementor statistics = getFactory().getStatistics(); if ( statistics.isStatisticsEnabled() ) { statistics.updateCollection( descriptor.getRole() ); } } ); firePostUpdate(entity, id, state, persister); final StatisticsImplementor statistics = getFactory().getStatistics(); if ( statistics.isStatisticsEnabled() ) { statistics.updateEntity( persister.getEntityName() ); } } } @Override public void upsert(String entityName, Object entity) { checkOpen(); final EntityPersister persister = getEntityPersister( entityName, entity ); final Object id = idToUpsert( entity, persister ); final Object[] state = persister.getValues( entity ); if ( !firePreUpsert(entity, id, state, persister) ) { getInterceptor() .onUpsert( entity, id, state, persister.getPropertyNames(), persister.getPropertyTypes() ); final Object oldVersion = versionToUpsert( entity, persister, state ); persister.getMergeCoordinator().update( entity, id, null, state, oldVersion, null, null, false, this ); // TODO: statistics for upsert! forEachOwnedCollection( entity, id, persister, (descriptor, collection) -> { // TODO: can we do better here? descriptor.remove( id, this ); descriptor.recreate( collection, id, this ); final StatisticsImplementor statistics = getFactory().getStatistics(); if ( statistics.isStatisticsEnabled() ) { statistics.updateCollection( descriptor.getRole() ); } } ); firePostUpsert(entity, id, state, persister); } } private Object versionToUpsert(Object entity, EntityPersister persister, Object[] state) { if ( persister.isVersioned() ) { final Object oldVersion = persister.getVersion( entity ); final Boolean knownTransient = persister.getVersionMapping() .getUnsavedStrategy() .isUnsaved( oldVersion ); if ( knownTransient != null && knownTransient ) { if ( seedVersion( entity, state, persister, this ) ) { persister.setValues( entity, state ); } // this is a nonsense but avoids setting version restriction // parameter to null later on deep in the guts return state[persister.getVersionProperty()]; } else { final Object newVersion = incrementVersion( entity, oldVersion, persister, this ); setVersion( state, newVersion, persister ); persister.setValues( entity, state ); return oldVersion; } } else { return null; } } private Object idToUpsert(Object entity, EntityPersister persister) { final Object id = persister.getIdentifier( entity, this ); final Boolean unsaved = persister.getIdentifierMapping() .getUnsavedStrategy() .isUnsaved( id ); if ( unsaved != null && unsaved ) { throw new TransientObjectException( "Object passed to upsert() has an unsaved identifier value: " + persister.getEntityName() ); } return id; } // event processing ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ private boolean firePreInsert(Object entity, Object id, Object[] state, EntityPersister persister) { if ( fastSessionServices.eventListenerGroup_PRE_INSERT.isEmpty() ) { return false; } else { boolean veto = false; final PreInsertEvent event = new PreInsertEvent( entity, id, state, persister, null ); for ( PreInsertEventListener listener : fastSessionServices.eventListenerGroup_PRE_INSERT.listeners() ) { veto |= listener.onPreInsert( event ); } return veto; } } private boolean firePreUpdate(Object entity, Object id, Object[] state, EntityPersister persister) { if ( fastSessionServices.eventListenerGroup_PRE_UPDATE.isEmpty() ) { return false; } else { boolean veto = false; final PreUpdateEvent event = new PreUpdateEvent( entity, id, state, null, persister, null ); for ( PreUpdateEventListener listener : fastSessionServices.eventListenerGroup_PRE_UPDATE.listeners() ) { veto |= listener.onPreUpdate( event ); } return veto; } } private boolean firePreUpsert(Object entity, Object id, Object[] state, EntityPersister persister) { if ( fastSessionServices.eventListenerGroup_PRE_UPSERT.isEmpty() ) { return false; } else { boolean veto = false; final PreUpsertEvent event = new PreUpsertEvent( entity, id, state, persister, null ); for ( PreUpsertEventListener listener : fastSessionServices.eventListenerGroup_PRE_UPSERT.listeners() ) { veto |= listener.onPreUpsert( event ); } return veto; } } private boolean firePreDelete(Object entity, Object id, EntityPersister persister) { if ( fastSessionServices.eventListenerGroup_PRE_DELETE.isEmpty() ) { return false; } else { boolean veto = false; final PreDeleteEvent event = new PreDeleteEvent( entity, id, null, persister, null ); for ( PreDeleteEventListener listener : fastSessionServices.eventListenerGroup_PRE_DELETE.listeners() ) { veto |= listener.onPreDelete( event ); } return veto; } } private void firePostInsert(Object entity, Object id, Object[] state, EntityPersister persister) { if ( !fastSessionServices.eventListenerGroup_POST_INSERT.isEmpty() ) { final PostInsertEvent event = new PostInsertEvent( entity, id, state, persister, null ); for ( PostInsertEventListener listener : fastSessionServices.eventListenerGroup_POST_INSERT.listeners() ) { listener.onPostInsert( event ); } } } private void firePostUpdate(Object entity, Object id, Object[] state, EntityPersister persister) { if ( !fastSessionServices.eventListenerGroup_POST_UPDATE.isEmpty() ) { final PostUpdateEvent event = new PostUpdateEvent( entity, id, state, null, null, persister, null ); for ( PostUpdateEventListener listener : fastSessionServices.eventListenerGroup_POST_UPDATE.listeners() ) { listener.onPostUpdate( event ); } } } private void firePostUpsert(Object entity, Object id, Object[] state, EntityPersister persister) { if ( !fastSessionServices.eventListenerGroup_POST_UPSERT.isEmpty() ) { final PostUpsertEvent event = new PostUpsertEvent( entity, id, state, null, persister, null ); for ( PostUpsertEventListener listener : fastSessionServices.eventListenerGroup_POST_UPSERT.listeners() ) { listener.onPostUpsert( event ); } } } private void firePostDelete(Object entity, Object id, EntityPersister persister) { if (!fastSessionServices.eventListenerGroup_POST_DELETE.isEmpty()) { final PostDeleteEvent event = new PostDeleteEvent( entity, id, null, persister, null ); for ( PostDeleteEventListener listener : fastSessionServices.eventListenerGroup_POST_DELETE.listeners() ) { listener.onPostDelete( event ); } } } // collections ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ private void forEachOwnedCollection( Object entity, Object key, EntityPersister persister, BiConsumer> action) { persister.visitAttributeMappings( att -> { if ( att.isPluralAttributeMapping() ) { final PluralAttributeMapping pluralAttributeMapping = att.asPluralAttributeMapping(); final CollectionPersister descriptor = pluralAttributeMapping.getCollectionDescriptor(); if ( !descriptor.isInverse() ) { final Object collection = att.getPropertyAccess().getGetter().get(entity); final PersistentCollection persistentCollection; if (collection instanceof PersistentCollection) { persistentCollection = (PersistentCollection) collection; if ( !persistentCollection.wasInitialized() ) { return; } } else { persistentCollection = collection == null ? instantiateEmpty(key, descriptor) : wrap(descriptor, collection); } action.accept(descriptor, persistentCollection); } } } ); } private PersistentCollection instantiateEmpty(Object key, CollectionPersister descriptor) { return descriptor.getCollectionSemantics().instantiateWrapper(key, descriptor, this); } //TODO: is this the right way to do this? @SuppressWarnings({"rawtypes", "unchecked"}) private PersistentCollection wrap(CollectionPersister descriptor, Object collection) { final CollectionSemantics collectionSemantics = descriptor.getCollectionSemantics(); return collectionSemantics.wrap(collection, descriptor, this); } // loading ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @Override @SuppressWarnings("unchecked") public T get(Class entityClass, Object id) { return (T) get( entityClass.getName(), id ); } @Override @SuppressWarnings("unchecked") public T get(Class entityClass, Object id, LockMode lockMode) { return (T) get( entityClass.getName(), id, lockMode ); } @Override public Object get(String entityName, Object id) { return get( entityName, id, LockMode.NONE ); } @Override public Object get(String entityName, Object id, LockMode lockMode) { checkOpen(); final Object result = getEntityPersister( entityName ) .load( id, null, getNullSafeLockMode( lockMode ), this ); if ( temporaryPersistenceContext.isLoadFinished() ) { temporaryPersistenceContext.clear(); } return result; } @Override public T get(EntityGraph graph, GraphSemantic graphSemantic, Object id) { return get( graph, graphSemantic, id, LockMode.NONE ); } @Override @SuppressWarnings("unchecked") public T get( EntityGraph graph, GraphSemantic graphSemantic, Object id, LockMode lockMode) { final RootGraphImplementor rootGraph = (RootGraphImplementor) 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 ); } @Override public void refresh(Object entity) { refresh( bestGuessEntityName( entity ), entity, LockMode.NONE ); } @Override public void refresh(String entityName, Object entity) { refresh( entityName, entity, LockMode.NONE ); } @Override public void refresh(Object entity, LockMode lockMode) { refresh( bestGuessEntityName( entity ), entity, lockMode ); } @Override public void refresh(String entityName, Object entity, LockMode lockMode) { checkOpen(); final EntityPersister persister = getEntityPersister( entityName, entity ); final Object id = persister.getIdentifier( entity, this ); if ( LOG.isTraceEnabled() ) { LOG.tracev( "Refreshing transient {0}", infoString( persister, id, getFactory() ) ); } if ( persister.canWriteToCache() ) { final EntityDataAccess cacheAccess = persister.getCacheAccessStrategy(); if ( cacheAccess != null ) { final Object ck = cacheAccess.generateCacheKey( id, persister, getFactory(), getTenantIdentifier() ); cacheAccess.evict( ck ); } } 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(); } } @Override public Object immediateLoad(String entityName, Object id) throws HibernateException { if ( getPersistenceContextInternal().isLoadFinished() ) { throw new SessionException( "proxies cannot be fetched by a stateless session" ); } // unless we are still in the process of handling a top-level load return get( entityName, id ); } @Override public void initializeCollection(PersistentCollection collection, boolean writing) throws HibernateException { checkOpen(); 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" ); } final StatisticsImplementor statistics = getFactory().getStatistics(); if ( statistics.isStatisticsEnabled() ) { statistics.fetchCollection( loadedPersister.getRole() ); } } } @Override public Object instantiate(String entityName, Object id) throws HibernateException { return instantiate( getEntityPersister( entityName ), id ); } @Override public Object instantiate(EntityPersister persister, Object id) throws HibernateException { checkOpen(); return persister.instantiate( id, this ); } @Override public Object internalLoad( String entityName, Object id, boolean eager, boolean nullable) throws HibernateException { checkOpen(); final EntityPersister persister = getEntityPersister( entityName ); final EntityKey entityKey = generateEntityKey( id, persister ); // first, try to load it from the temp PC associated to this SS final PersistenceContext persistenceContext = getPersistenceContext(); final EntityHolder holder = persistenceContext.getEntityHolder( entityKey ); if ( holder != null && holder.getEntity() != null ) { // we found it in the temp PC. Should indicate we are in the midst of processing a result set // containing eager fetches via join fetch return holder.getEntity(); } if ( !eager ) { // caller did not request forceful eager loading, see if we can create // some form of proxy // first, check to see if we can use "bytecode proxies" final EntityMetamodel entityMetamodel = persister.getEntityMetamodel(); final BytecodeEnhancementMetadata enhancementMetadata = entityMetamodel.getBytecodeEnhancementMetadata(); if ( enhancementMetadata.isEnhancedForLazyLoading() ) { // if the entity defines a HibernateProxy factory, see if there is an // existing proxy associated with the PC - and if so, use it if ( persister.getRepresentationStrategy().getProxyFactory() != null ) { final Object proxy = holder == null ? null : holder.getProxy(); if ( proxy != null ) { if ( LOG.isTraceEnabled() ) { LOG.trace( "Entity proxy found in session cache" ); } if ( LOG.isDebugEnabled() && extractLazyInitializer( proxy ).isUnwrap() ) { LOG.debug( "Ignoring NO_PROXY to honor laziness" ); } return persistenceContext.narrowProxy( proxy, persister, entityKey, null ); } // specialized handling for entities with subclasses with a HibernateProxy factory if ( entityMetamodel.hasSubclasses() ) { // entities with subclasses that define a ProxyFactory can create // a HibernateProxy. LOG.debug( "Creating a HibernateProxy for to-one association with subclasses to honor laziness" ); return createProxy( entityKey ); } return enhancementMetadata.createEnhancedProxy( entityKey, false, this ); } else if ( !entityMetamodel.hasSubclasses() ) { return enhancementMetadata.createEnhancedProxy( entityKey, false, this ); } // If we get here, then the entity class has subclasses and there is no HibernateProxy factory. // The entity will get loaded below. } else { if ( persister.hasProxy() ) { final Object existingProxy = holder == null ? null : holder.getProxy(); if ( existingProxy != null ) { return persistenceContext.narrowProxy( existingProxy, persister, entityKey, null ); } else { return createProxy( entityKey ); } } } } // otherwise immediately materialize it // IMPLEMENTATION NOTE: increment/decrement the load count before/after getting the value // to ensure that #get does not clear the PersistenceContext. persistenceContext.beforeLoad(); try { return get( entityName, id ); } finally { persistenceContext.afterLoad(); } } private Object createProxy(EntityKey entityKey) { final Object proxy = entityKey.getPersister().createProxy( entityKey.getIdentifier(), this ); getPersistenceContext().addProxy( entityKey, proxy ); return proxy; } @Override public void fetch(Object association) { checkOpen(); final PersistenceContext persistenceContext = getPersistenceContext(); final LazyInitializer initializer = extractLazyInitializer( association ); if ( initializer != null ) { if ( initializer.isUninitialized() ) { final String entityName = initializer.getEntityName(); final Object id = initializer.getIdentifier(); initializer.setSession( this ); persistenceContext.beforeLoad(); try { final Object entity = initializer.getImplementation(); //forces the load to occur if ( entity==null ) { getFactory().getEntityNotFoundDelegate().handleEntityNotFound( entityName, id ); } initializer.setImplementation( entity ); } finally { initializer.unsetSession(); persistenceContext.afterLoad(); if ( persistenceContext.isLoadFinished() ) { persistenceContext.clear(); } } } } else if ( isPersistentAttributeInterceptable( association ) ) { final PersistentAttributeInterceptable interceptable = asPersistentAttributeInterceptable( association ); final PersistentAttributeInterceptor interceptor = interceptable.$$_hibernate_getInterceptor(); if ( interceptor instanceof EnhancementAsProxyLazinessInterceptor ) { final EnhancementAsProxyLazinessInterceptor proxyInterceptor = (EnhancementAsProxyLazinessInterceptor) interceptor; proxyInterceptor.setSession( this ); try { proxyInterceptor.forceInitialize( association, null ); // TODO: statistics?? call statistics.fetchEntity() } finally { proxyInterceptor.unsetSession(); if ( persistenceContext.isLoadFinished() ) { persistenceContext.clear(); } } } } else if ( association instanceof PersistentCollection ) { final PersistentCollection persistentCollection = (PersistentCollection) association; if ( !persistentCollection.wasInitialized() ) { final CollectionPersister collectionDescriptor = getFactory().getMappingMetamodel() .getCollectionDescriptor( persistentCollection.getRole() ); final Object key = persistentCollection.getKey(); persistenceContext.addUninitializedCollection( collectionDescriptor, persistentCollection, key ); persistentCollection.setCurrentSession( this ); try { collectionDescriptor.initialize( key, this ); handlePotentiallyEmptyCollection( persistentCollection, getPersistenceContextInternal(), key, collectionDescriptor ); final StatisticsImplementor statistics = getFactory().getStatistics(); if ( statistics.isStatisticsEnabled() ) { statistics.fetchCollection( collectionDescriptor.getRole() ); } } finally { persistentCollection.unsetSession( this ); if ( persistenceContext.isLoadFinished() ) { persistenceContext.clear(); } } } } } @Override public Object getIdentifier(Object entity) throws HibernateException { checkOpen(); return getFactory().getPersistenceUnitUtil().getIdentifier(entity); } @Override public boolean isAutoCloseSessionEnabled() { return getFactory().getSessionFactoryOptions().isAutoCloseSessionEnabled(); } @Override public boolean shouldAutoClose() { return isAutoCloseSessionEnabled() && !isClosed(); } private boolean isFlushModeNever() { return false; } private void managedClose() { if ( isClosed() ) { throw new SessionException( "Session was already closed" ); } close(); } private void managedFlush() { checkOpen(); getJdbcCoordinator().executeBatch(); } @Override public String bestGuessEntityName(Object object) { final LazyInitializer lazyInitializer = extractLazyInitializer( object ); if ( lazyInitializer != null ) { object = lazyInitializer.getImplementation(); } return guessEntityName( object ); } @Override public CacheMode getCacheMode() { return CacheMode.IGNORE; } @Override public void setCacheMode(CacheMode cm) { throw new UnsupportedOperationException(); } @Override public void setHibernateFlushMode(FlushMode flushMode) { throw new UnsupportedOperationException(); } @Override public Object getContextEntityIdentifier(Object object) { checkOpen(); return null; } @Override public String guessEntityName(Object entity) throws HibernateException { checkOpen(); return entity.getClass().getName(); } @Override public EntityPersister getEntityPersister(String entityName, Object object) throws HibernateException { checkOpen(); return entityName == null ? getEntityPersister( guessEntityName( object ) ) : getEntityPersister( entityName ).getSubclassEntityPersister( object, getFactory() ); } @Override public Object getEntityUsingInterceptor(EntityKey key) throws HibernateException { checkOpen(); final PersistenceContext persistenceContext = getPersistenceContext(); final Object result = persistenceContext.getEntity( key ); if ( result != null ) { return result; } final Object newObject = getInterceptor().getEntity( key.getEntityName(), key.getIdentifier() ); if ( newObject != null ) { persistenceContext.addEntity( key, newObject ); return newObject; } return null; } @Override public PersistenceContext getPersistenceContext() { return temporaryPersistenceContext; } @Override public void setAutoClear(boolean enabled) { throw new UnsupportedOperationException(); } @Override protected Object load(String entityName, Object identifier) { return null; } public boolean isDefaultReadOnly() { return false; } public void setDefaultReadOnly(boolean readOnly) throws HibernateException { if ( readOnly ) { throw new UnsupportedOperationException(); } } ///////////////////////////////////////////////////////////////////////////////////////////////////// //TODO: COPY/PASTE FROM SessionImpl, pull up! public void afterOperation(boolean success) { temporaryPersistenceContext.clear(); if ( !isTransactionInProgress() ) { getJdbcCoordinator().afterTransaction(); } } @Override public void afterScrollOperation() { temporaryPersistenceContext.clear(); } @Override public void flush() { } @Override public LoadQueryInfluencers getLoadQueryInfluencers() { return influencers; } @Override public PersistenceContext getPersistenceContextInternal() { //In this case implemented the same as #getPersistenceContext return temporaryPersistenceContext; } @Override public boolean autoFlushIfRequired(Set querySpaces) throws HibernateException { return false; } @Override public void afterTransactionBegin() { afterTransactionBeginEvents(); } @Override public void beforeTransactionCompletion() { flushBeforeTransactionCompletion(); beforeTransactionCompletionEvents(); } @Override public void afterTransactionCompletion(boolean successful, boolean delayed) { afterTransactionCompletionEvents( successful ); if ( shouldAutoClose() && !isClosed() ) { managedClose(); } } @Override public boolean isTransactionInProgress() { return connectionProvided || super.isTransactionInProgress(); } @Override public void flushBeforeTransactionCompletion() { boolean flush; try { flush = !isClosed() && !isFlushModeNever() && !JtaStatusHelper.isRollback( getJtaPlatform().getCurrentStatus() ); } catch ( SystemException se ) { throw new HibernateException( "could not determine transaction status in beforeCompletion()", se ); } if ( flush ) { managedFlush(); } } private JtaPlatform getJtaPlatform() { return getFactory().getServiceRegistry().requireService( JtaPlatform.class ); } private LockMode getNullSafeLockMode(LockMode lockMode) { return lockMode == null ? LockMode.NONE : lockMode; } @Override public StatelessSession asStatelessSession() { return this; } @Override public boolean isStatelessSession() { return true; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy