package org.hibernate.internal;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Reader;
import java.io.Serializable;
import java.sql.Blob;
import java.sql.Clob;
import java.sql.Connection;
import java.sql.NClob;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.persistence.EntityNotFoundException;
import org.hibernate.AssertionFailure;
import org.hibernate.CacheMode;
import org.hibernate.ConnectionReleaseMode;
import org.hibernate.Criteria;
import org.hibernate.EmptyInterceptor;
import org.hibernate.EntityNameResolver;
import org.hibernate.Filter;
import org.hibernate.FlushMode;
import org.hibernate.HibernateException;
import org.hibernate.IdentifierLoadAccess;
import org.hibernate.Interceptor;
import org.hibernate.LobHelper;
import org.hibernate.LockMode;
import org.hibernate.LockOptions;
import org.hibernate.MappingException;
import org.hibernate.NaturalIdLoadAccess;
import org.hibernate.ObjectDeletedException;
import org.hibernate.ObjectNotFoundException;
import org.hibernate.Query;
import org.hibernate.QueryException;
import org.hibernate.ReplicationMode;
import org.hibernate.SQLQuery;
import org.hibernate.ScrollMode;
import org.hibernate.ScrollableResults;
import org.hibernate.Session;
import org.hibernate.SessionBuilder;
import org.hibernate.SessionEventListener;
import org.hibernate.SessionException;
import org.hibernate.SharedSessionBuilder;
import org.hibernate.SimpleNaturalIdLoadAccess;
import org.hibernate.Transaction;
import org.hibernate.TransientObjectException;
import org.hibernate.TypeHelper;
import org.hibernate.UnknownProfileException;
import org.hibernate.UnresolvableObjectException;
import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.criterion.NaturalIdentifier;
import org.hibernate.engine.internal.SessionEventListenerManagerImpl;
import org.hibernate.engine.internal.StatefulPersistenceContext;
import org.hibernate.engine.jdbc.LobCreator;
import org.hibernate.engine.jdbc.NonContextualLobCreator;
import org.hibernate.engine.query.spi.FilterQueryPlan;
import org.hibernate.engine.query.spi.HQLQueryPlan;
import org.hibernate.engine.query.spi.NativeSQLQueryPlan;
import org.hibernate.engine.query.spi.sql.NativeSQLQuerySpecification;
import org.hibernate.engine.spi.ActionQueue;
import org.hibernate.engine.spi.CollectionEntry;
import org.hibernate.engine.spi.EntityEntry;
import org.hibernate.engine.spi.EntityKey;
import org.hibernate.engine.spi.LoadQueryInfluencers;
import org.hibernate.engine.spi.PersistenceContext;
import org.hibernate.engine.spi.QueryParameters;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SessionOwner;
import org.hibernate.engine.spi.Status;
import org.hibernate.engine.transaction.internal.TransactionCoordinatorImpl;
import org.hibernate.engine.transaction.spi.TransactionCoordinator;
import org.hibernate.engine.transaction.spi.TransactionImplementor;
import org.hibernate.engine.transaction.spi.TransactionObserver;
import org.hibernate.event.service.spi.EventListenerGroup;
import org.hibernate.event.service.spi.EventListenerRegistry;
import org.hibernate.event.spi.AutoFlushEvent;
import org.hibernate.event.spi.AutoFlushEventListener;
import org.hibernate.event.spi.ClearEvent;
import org.hibernate.event.spi.ClearEventListener;
import org.hibernate.event.spi.DeleteEvent;
import org.hibernate.event.spi.DeleteEventListener;
import org.hibernate.event.spi.DirtyCheckEvent;
import org.hibernate.event.spi.DirtyCheckEventListener;
import org.hibernate.event.spi.EventSource;
import org.hibernate.event.spi.EventType;
import org.hibernate.event.spi.EvictEvent;
import org.hibernate.event.spi.EvictEventListener;
import org.hibernate.event.spi.FlushEvent;
import org.hibernate.event.spi.FlushEventListener;
import org.hibernate.event.spi.InitializeCollectionEvent;
import org.hibernate.event.spi.InitializeCollectionEventListener;
import org.hibernate.event.spi.LoadEvent;
import org.hibernate.event.spi.LoadEventListener;
import org.hibernate.event.spi.LoadEventListener.LoadType;
import org.hibernate.event.spi.LockEvent;
import org.hibernate.event.spi.LockEventListener;
import org.hibernate.event.spi.MergeEvent;
import org.hibernate.event.spi.MergeEventListener;
import org.hibernate.event.spi.PersistEvent;
import org.hibernate.event.spi.PersistEventListener;
import org.hibernate.event.spi.RefreshEvent;
import org.hibernate.event.spi.RefreshEventListener;
import org.hibernate.event.spi.ReplicateEvent;
import org.hibernate.event.spi.ReplicateEventListener;
import org.hibernate.event.spi.ResolveNaturalIdEvent;
import org.hibernate.event.spi.ResolveNaturalIdEventListener;
import org.hibernate.event.spi.SaveOrUpdateEvent;
import org.hibernate.event.spi.SaveOrUpdateEventListener;
import org.hibernate.internal.CriteriaImpl.CriterionEntry;
import org.hibernate.jdbc.ReturningWork;
import org.hibernate.jdbc.Work;
import org.hibernate.jdbc.WorkExecutor;
import org.hibernate.jdbc.WorkExecutorVisitable;
import org.hibernate.loader.criteria.CriteriaLoader;
import org.hibernate.loader.custom.CustomLoader;
import org.hibernate.loader.custom.CustomQuery;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.entity.OuterJoinLoadable;
import org.hibernate.pretty.MessageHelper;
import org.hibernate.procedure.ProcedureCall;
import org.hibernate.proxy.HibernateProxy;
import org.hibernate.proxy.LazyInitializer;
import org.hibernate.stat.SessionStatistics;
import org.hibernate.stat.internal.SessionStatisticsImpl;
import org.hibernate.type.Type;
import org.jboss.logging.Logger;
public final class SessionImpl extends AbstractSessionImpl implements EventSource {
private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, SessionImpl.class.getName());
private static final boolean TRACE_ENABLED = LOG.isTraceEnabled();
private transient long timestamp;
private transient SessionOwner sessionOwner;
private transient ActionQueue actionQueue;
private transient StatefulPersistenceContext persistenceContext;
private transient TransactionCoordinatorImpl transactionCoordinator;
private transient Interceptor interceptor;
private transient EntityNameResolver entityNameResolver = new CoordinatingEntityNameResolver();
private transient ConnectionReleaseMode connectionReleaseMode;
private transient FlushMode flushMode = FlushMode.AUTO;
private transient CacheMode cacheMode = CacheMode.NORMAL;
private transient boolean autoClear;
private transient boolean autoJoinTransactions = true;
private transient boolean flushBeforeCompletionEnabled;
private transient boolean autoCloseSessionEnabled;
private transient int dontFlushFromFind;
private transient LoadQueryInfluencers loadQueryInfluencers;
private final transient boolean isTransactionCoordinatorShared;
private transient TransactionObserver transactionObserver;
private SessionEventListenerManagerImpl sessionEventsManager = new SessionEventListenerManagerImpl();
SessionImpl(
final Connection connection,
final SessionFactoryImpl factory,
final SessionOwner sessionOwner,
final TransactionCoordinatorImpl transactionCoordinator,
final ActionQueue.TransactionCompletionProcesses transactionCompletionProcesses,
final boolean autoJoinTransactions,
final long timestamp,
final Interceptor interceptor,
final boolean flushBeforeCompletionEnabled,
final boolean autoCloseSessionEnabled,
final ConnectionReleaseMode connectionReleaseMode,
final String tenantIdentifier) {
super( factory, tenantIdentifier );
this.timestamp = timestamp;
this.sessionOwner = sessionOwner;
this.interceptor = interceptor == null ? EmptyInterceptor.INSTANCE : interceptor;
this.actionQueue = new ActionQueue( this );
this.persistenceContext = new StatefulPersistenceContext( this );
this.autoCloseSessionEnabled = autoCloseSessionEnabled;
this.flushBeforeCompletionEnabled = flushBeforeCompletionEnabled;
if ( transactionCoordinator == null ) {
this.isTransactionCoordinatorShared = false;
this.connectionReleaseMode = connectionReleaseMode;
this.autoJoinTransactions = autoJoinTransactions;
this.transactionCoordinator = new TransactionCoordinatorImpl( connection, this );
this.transactionCoordinator.getJdbcCoordinator().getLogicalConnection().addObserver(
new ConnectionObserverStatsBridge( factory )
);
}
else {
if ( connection != null ) {
throw new SessionException( "Cannot simultaneously share transaction context and specify connection" );
}
this.transactionCoordinator = transactionCoordinator;
this.isTransactionCoordinatorShared = true;
this.autoJoinTransactions = false;
if ( transactionCompletionProcesses != null ) {
actionQueue.setTransactionCompletionProcesses( transactionCompletionProcesses, true );
}
if ( autoJoinTransactions ) {
LOG.debug(
"Session creation specified 'autoJoinTransactions', which is invalid in conjunction " +
"with sharing JDBC connection between sessions; ignoring"
);
}
if ( connectionReleaseMode != transactionCoordinator.getJdbcCoordinator().getLogicalConnection().getConnectionReleaseMode() ) {
LOG.debug(
"Session creation specified 'connectionReleaseMode', which is invalid in conjunction " +
"with sharing JDBC connection between sessions; ignoring"
);
}
this.connectionReleaseMode = transactionCoordinator.getJdbcCoordinator().getLogicalConnection().getConnectionReleaseMode();
transactionObserver = new TransactionObserver() {
@Override
public void afterBegin(TransactionImplementor transaction) {
}
@Override
public void beforeCompletion(TransactionImplementor transaction) {
if ( isOpen() && flushBeforeCompletionEnabled ) {
SessionImpl.this.managedFlush();
}
beforeTransactionCompletion( transaction );
}
@Override
public void afterCompletion(boolean successful, TransactionImplementor transaction) {
afterTransactionCompletion( transaction, successful );
if ( isOpen() && autoCloseSessionEnabled ) {
managedClose();
}
transactionCoordinator.removeObserver( this );
}
};
transactionCoordinator.addObserver( transactionObserver );
}
loadQueryInfluencers = new LoadQueryInfluencers( factory );
if (factory.getStatistics().isStatisticsEnabled()) {
factory.getStatisticsImplementor().openSession();
}
if ( TRACE_ENABLED )
LOG.tracef( "Opened session at timestamp: %s", timestamp );
}
@Override
public SharedSessionBuilder sessionWithOptions() {
return new SharedSessionBuilderImpl( this );
}
@Override
public void clear() {
errorIfClosed();
pulseTransactionCoordinator();
internalClear();
}
private void internalClear() {
persistenceContext.clear();
actionQueue.clear();
final ClearEvent event = new ClearEvent( this );
for ( ClearEventListener listener : listeners( EventType.CLEAR ) ) {
listener.onClear( event );
}
}
@Override
public long getTimestamp() {
checkTransactionSynchStatus();
return timestamp;
}
@Override
public Connection close() throws HibernateException {
LOG.trace( "Closing session" );
if ( isClosed() ) {
throw new SessionException( "Session was already closed" );
}
if ( factory.getStatistics().isStatisticsEnabled() ) {
factory.getStatisticsImplementor().closeSession();
}
getEventListenerManager().end();
try {
if ( !isTransactionCoordinatorShared ) {
return transactionCoordinator.close();
}
else {
if ( getActionQueue().hasBeforeTransactionActions() || getActionQueue().hasAfterTransactionActions() ) {
LOG.warn( "On close, shared Session had before / after transaction actions that have not yet been processed" );
}
else {
transactionCoordinator.removeObserver( transactionObserver );
}
return null;
}
}
finally {
setClosed();
cleanup();
}
}
@Override
public ConnectionReleaseMode getConnectionReleaseMode() {
return connectionReleaseMode;
}
@Override
public boolean shouldAutoJoinTransaction() {
return autoJoinTransactions;
}
@Override
public boolean isAutoCloseSessionEnabled() {
return autoCloseSessionEnabled;
}
@Override
public boolean isOpen() {
checkTransactionSynchStatus();
return !isClosed();
}
@Override
public boolean isFlushModeNever() {
return FlushMode.isManualFlushMode( getFlushMode() );
}
@Override
public boolean isFlushBeforeCompletionEnabled() {
return flushBeforeCompletionEnabled;
}
@Override
public void managedFlush() {
if ( isClosed() ) {
LOG.trace( "Skipping auto-flush due to session closed" );
return;
}
LOG.trace( "Automatically flushing session" );
flush();
}
@Override
public boolean shouldAutoClose() {
if ( isClosed() ) {
return false;
}
else if ( sessionOwner != null ) {
return sessionOwner.shouldAutoCloseSession();
}
else {
return isAutoCloseSessionEnabled();
}
}
@Override
public void managedClose() {
LOG.trace( "Automatically closing session" );
close();
}
@Override
public Connection connection() throws HibernateException {
errorIfClosed();
return transactionCoordinator.getJdbcCoordinator().getLogicalConnection().getConnection();
}
@Override
public boolean isConnected() {
checkTransactionSynchStatus();
return !isClosed() && transactionCoordinator.getJdbcCoordinator().getLogicalConnection().isOpen();
}
@Override
public boolean isTransactionInProgress() {
checkTransactionSynchStatus();
return !isClosed() && transactionCoordinator.isTransactionInProgress();
}
@Override
public Connection disconnect() throws HibernateException {
errorIfClosed();
LOG.debug( "Disconnecting session" );
transactionCoordinator.getJdbcCoordinator().releaseResources();
return transactionCoordinator.getJdbcCoordinator().getLogicalConnection().manualDisconnect();
}
@Override
public void reconnect(Connection conn) throws HibernateException {
errorIfClosed();
LOG.debug( "Reconnecting session" );
checkTransactionSynchStatus();
transactionCoordinator.getJdbcCoordinator().getLogicalConnection().manualReconnect( conn );
}
@Override
public void setAutoClear(boolean enabled) {
errorIfClosed();
autoClear = enabled;
}
@Override
public void disableTransactionAutoJoin() {
errorIfClosed();
autoJoinTransactions = false;
}
public void afterOperation(boolean success) {
if ( ! transactionCoordinator.isTransactionInProgress() ) {
transactionCoordinator.afterNonTransactionalQuery( success );
}
}
@Override
public void afterTransactionBegin(TransactionImplementor hibernateTransaction) {
errorIfClosed();
interceptor.afterTransactionBegin( hibernateTransaction );
}
@Override
public void beforeTransactionCompletion(TransactionImplementor hibernateTransaction) {
LOG.trace( "before transaction completion" );
actionQueue.beforeTransactionCompletion();
try {
interceptor.beforeTransactionCompletion( hibernateTransaction );
}
catch (Throwable t) {
LOG.exceptionInBeforeTransactionCompletionInterceptor( t );
}
}
@Override
public void afterTransactionCompletion(TransactionImplementor hibernateTransaction, boolean successful) {
LOG.trace( "after transaction completion" );
persistenceContext.afterTransactionCompletion();
actionQueue.afterTransactionCompletion( successful );
getEventListenerManager().transactionCompletion( successful );
try {
interceptor.afterTransactionCompletion( hibernateTransaction );
}
catch (Throwable t) {
LOG.exceptionInAfterTransactionCompletionInterceptor( t );
}
if ( autoClear ) {
internalClear();
}
}
@Override
public String onPrepareStatement(String sql) {
errorIfClosed();
sql = interceptor.onPrepareStatement( sql );
if ( sql == null || sql.length() == 0 ) {
throw new AssertionFailure( "Interceptor.onPrepareStatement() returned null or empty string." );
}
return sql;
}
@Override
public SessionEventListenerManagerImpl getEventListenerManager() {
return sessionEventsManager;
}
@Override
public void addEventListeners(SessionEventListener... listeners) {
getEventListenerManager().addListener( listeners );
}
@Override
public void startPrepareStatement() {
getEventListenerManager().jdbcPrepareStatementStart();
}
@Override
public void endPrepareStatement() {
getEventListenerManager().jdbcPrepareStatementEnd();
}
@Override
public void startStatementExecution() {
getEventListenerManager().jdbcExecuteStatementStart();
}
@Override
public void endStatementExecution() {
getEventListenerManager().jdbcExecuteStatementEnd();
}
@Override
public void startBatchExecution() {
getEventListenerManager().jdbcExecuteBatchStart();
}
@Override
public void endBatchExecution() {
getEventListenerManager().jdbcExecuteBatchEnd();
}
private void cleanup() {
persistenceContext.clear();
}
@Override
public LockMode getCurrentLockMode(Object object) throws HibernateException {
errorIfClosed();
checkTransactionSynchStatus();
if ( object == null ) {
throw new NullPointerException( "null object passed to getCurrentLockMode()" );
}
if ( object instanceof HibernateProxy ) {
object = ( (HibernateProxy) object ).getHibernateLazyInitializer().getImplementation(this);
if ( object == null ) {
return LockMode.NONE;
}
}
EntityEntry e = persistenceContext.getEntry(object);
if ( e == null ) {
throw new TransientObjectException( "Given object not associated with the session" );
}
if ( e.getStatus() != Status.MANAGED ) {
throw new ObjectDeletedException(
"The given object was deleted",
e.getId(),
e.getPersister().getEntityName()
);
}
return e.getLockMode();
}
@Override
public Object getEntityUsingInterceptor(EntityKey key) throws HibernateException {
errorIfClosed();
final Object result = persistenceContext.getEntity(key);
if ( result == null ) {
final Object newObject = interceptor.getEntity( key.getEntityName(), key.getIdentifier() );
if ( newObject != null ) {
lock( newObject, LockMode.NONE );
}
return newObject;
}
else {
return result;
}
}
private void checkNoUnresolvedActionsBeforeOperation() {
if ( persistenceContext.getCascadeLevel() == 0 && actionQueue.hasUnresolvedEntityInsertActions() ) {
throw new IllegalStateException( "There are delayed insert actions before operation as cascade level 0." );
}
}
private void checkNoUnresolvedActionsAfterOperation() {
if ( persistenceContext.getCascadeLevel() == 0 ) {
actionQueue.checkNoUnresolvedActionsAfterOperation();
}
delayedAfterCompletion();
}
private void delayedAfterCompletion() {
transactionCoordinator.getSynchronizationCallbackCoordinator().processAnyDelayedAfterCompletion();
}
@Override
public void saveOrUpdate(Object object) throws HibernateException {
saveOrUpdate( null, object );
}
@Override
public void saveOrUpdate(String entityName, Object obj) throws HibernateException {
fireSaveOrUpdate( new SaveOrUpdateEvent( entityName, obj, this ) );
}
private void fireSaveOrUpdate(SaveOrUpdateEvent event) {
errorIfClosed();
checkTransactionSynchStatus();
checkNoUnresolvedActionsBeforeOperation();
for ( SaveOrUpdateEventListener listener : listeners( EventType.SAVE_UPDATE ) ) {
listener.onSaveOrUpdate( event );
}
checkNoUnresolvedActionsAfterOperation();
}
private <T> Iterable<T> listeners(EventType<T> type) {
return eventListenerGroup( type ).listeners();
}
private <T> EventListenerGroup<T> eventListenerGroup(EventType<T> type) {
return factory.getServiceRegistry().getService( EventListenerRegistry.class ).getEventListenerGroup( type );
}
@Override
public Serializable save(Object obj) throws HibernateException {
return save( null, obj );
}
@Override
public Serializable save(String entityName, Object object) throws HibernateException {
return fireSave( new SaveOrUpdateEvent( entityName, object, this ) );
}
private Serializable fireSave(SaveOrUpdateEvent event) {
errorIfClosed();
checkTransactionSynchStatus();
checkNoUnresolvedActionsBeforeOperation();
for ( SaveOrUpdateEventListener listener : listeners( EventType.SAVE ) ) {
listener.onSaveOrUpdate( event );
}
checkNoUnresolvedActionsAfterOperation();
return event.getResultId();
}
@Override
public void update(Object obj) throws HibernateException {
update( null, obj );
}
@Override
public void update(String entityName, Object object) throws HibernateException {
fireUpdate( new SaveOrUpdateEvent( entityName, object, this ) );
}
private void fireUpdate(SaveOrUpdateEvent event) {
errorIfClosed();
checkTransactionSynchStatus();
checkNoUnresolvedActionsBeforeOperation();
for ( SaveOrUpdateEventListener listener : listeners( EventType.UPDATE ) ) {
listener.onSaveOrUpdate( event );
}
checkNoUnresolvedActionsAfterOperation();
}
@Override
public void lock(String entityName, Object object, LockMode lockMode) throws HibernateException {
fireLock( new LockEvent( entityName, object, lockMode, this ) );
}
@Override
public LockRequest buildLockRequest(LockOptions lockOptions) {
return new LockRequestImpl(lockOptions);
}
@Override
public void lock(Object object, LockMode lockMode) throws HibernateException {
fireLock( new LockEvent( object, lockMode, this ) );
}
private void fireLock(String entityName, Object object, LockOptions options) {
fireLock( new LockEvent( entityName, object, options, this) );
}
private void fireLock( Object object, LockOptions options) {
fireLock( new LockEvent( object, options, this ) );
}
private void fireLock(LockEvent event) {
errorIfClosed();
checkTransactionSynchStatus();
for ( LockEventListener listener : listeners( EventType.LOCK ) ) {
listener.onLock( event );
}
delayedAfterCompletion();
}
@Override
public void persist(String entityName, Object object) throws HibernateException {
firePersist( new PersistEvent( entityName, object, this ) );
}
@Override
public void persist(Object object) throws HibernateException {
persist( null, object );
}
@Override
public void persist(String entityName, Object object, Map copiedAlready) throws HibernateException {
firePersist( copiedAlready, new PersistEvent( entityName, object, this ) );
}
private void firePersist(Map copiedAlready, PersistEvent event) {
errorIfClosed();
checkTransactionSynchStatus();
for ( PersistEventListener listener : listeners( EventType.PERSIST ) ) {
listener.onPersist( event, copiedAlready );
}
delayedAfterCompletion();
}
private void firePersist(PersistEvent event) {
errorIfClosed();
checkTransactionSynchStatus();
checkNoUnresolvedActionsBeforeOperation();
for ( PersistEventListener listener : listeners( EventType.PERSIST ) ) {
listener.onPersist( event );
}
checkNoUnresolvedActionsAfterOperation();
}
public void persistOnFlush(String entityName, Object object)
throws HibernateException {
firePersistOnFlush( new PersistEvent( entityName, object, this ) );
}
public void persistOnFlush(Object object) throws HibernateException {
persist( null, object );
}
@Override
public void persistOnFlush(String entityName, Object object, Map copiedAlready)
throws HibernateException {
firePersistOnFlush( copiedAlready, new PersistEvent( entityName, object, this ) );
}
private void firePersistOnFlush(Map copiedAlready, PersistEvent event) {
errorIfClosed();
checkTransactionSynchStatus();
for ( PersistEventListener listener : listeners( EventType.PERSIST_ONFLUSH ) ) {
listener.onPersist( event, copiedAlready );
}
delayedAfterCompletion();
}
private void firePersistOnFlush(PersistEvent event) {
errorIfClosed();
checkTransactionSynchStatus();
checkNoUnresolvedActionsBeforeOperation();
for ( PersistEventListener listener : listeners( EventType.PERSIST_ONFLUSH ) ) {
listener.onPersist( event );
}
checkNoUnresolvedActionsAfterOperation();
}
@Override
public Object merge(String entityName, Object object) throws HibernateException {
return fireMerge( new MergeEvent( entityName, object, this ) );
}
@Override
public Object merge(Object object) throws HibernateException {
return merge( null, object );
}
@Override
public void merge(String entityName, Object object, Map copiedAlready) throws HibernateException {
fireMerge( copiedAlready, new MergeEvent( entityName, object, this ) );
}
private Object fireMerge(MergeEvent event) {
errorIfClosed();
checkTransactionSynchStatus();
checkNoUnresolvedActionsBeforeOperation();
for ( MergeEventListener listener : listeners( EventType.MERGE ) ) {
listener.onMerge( event );
}
checkNoUnresolvedActionsAfterOperation();
return event.getResult();
}
private void fireMerge(Map copiedAlready, MergeEvent event) {
errorIfClosed();
checkTransactionSynchStatus();
for ( MergeEventListener listener : listeners( EventType.MERGE ) ) {
listener.onMerge( event, copiedAlready );
}
delayedAfterCompletion();
}
@Override
public void delete(Object object) throws HibernateException {
fireDelete( new DeleteEvent( object, this ) );
}
@Override
public void delete(String entityName, Object object) throws HibernateException {
fireDelete( new DeleteEvent( entityName, object, this ) );
}
@Override
public void delete(String entityName, Object object, boolean isCascadeDeleteEnabled, Set transientEntities) throws HibernateException {
if ( TRACE_ENABLED && persistenceContext.isRemovingOrphanBeforeUpates() ) {
logRemoveOrphanBeforeUpdates( "before continuing", entityName, object );
}
fireDelete(
new DeleteEvent(
entityName,
object,
isCascadeDeleteEnabled,
persistenceContext.isRemovingOrphanBeforeUpates(),
this
),
transientEntities
);
if ( TRACE_ENABLED && persistenceContext.isRemovingOrphanBeforeUpates() ) {
logRemoveOrphanBeforeUpdates( "after continuing", entityName, object );
}
}
@Override
public void removeOrphanBeforeUpdates(String entityName, Object child) {
if ( TRACE_ENABLED ) {
logRemoveOrphanBeforeUpdates( "begin", entityName, child );
}
persistenceContext.beginRemoveOrphanBeforeUpdates();
try {
fireDelete( new DeleteEvent( entityName, child, false, true, this ) );
}
finally {
persistenceContext.endRemoveOrphanBeforeUpdates();
if ( TRACE_ENABLED ) {
logRemoveOrphanBeforeUpdates( "end", entityName, child );
}
}
}
private void logRemoveOrphanBeforeUpdates(String timing, String entityName, Object entity) {
final EntityEntry entityEntry = persistenceContext.getEntry( entity );
LOG.tracef(
"%s remove orphan before updates: [%s]",
timing,
entityEntry == null ? entityName : MessageHelper.infoString( entityName, entityEntry.getId() )
);
}
private void fireDelete(DeleteEvent event) {
errorIfClosed();
checkTransactionSynchStatus();
for ( DeleteEventListener listener : listeners( EventType.DELETE ) ) {
listener.onDelete( event );
}
delayedAfterCompletion();
}
private void fireDelete(DeleteEvent event, Set transientEntities) {
errorIfClosed();
checkTransactionSynchStatus();
for ( DeleteEventListener listener : listeners( EventType.DELETE ) ) {
listener.onDelete( event, transientEntities );
}
delayedAfterCompletion();
}
@Override
public void load(Object object, Serializable id) throws HibernateException {
LoadEvent event = new LoadEvent(id, object, this);
fireLoad( event, LoadEventListener.RELOAD );
}
@Override
public Object load(Class entityClass, Serializable id) throws HibernateException {
return this.byId( entityClass ).getReference( id );
}
@Override
public Object load(String entityName, Serializable id) throws HibernateException {
return this.byId( entityName ).getReference( id );
}
@Override
public Object get(Class entityClass, Serializable id) throws HibernateException {
return this.byId( entityClass ).load( id );
}
@Override
public Object get(String entityName, Serializable id) throws HibernateException {
return this.byId( entityName ).load( id );
}
@Override
public Object immediateLoad(String entityName, Serializable id) throws HibernateException {
if ( LOG.isDebugEnabled() ) {
EntityPersister persister = getFactory().getEntityPersister(entityName);
LOG.debugf( "Initializing proxy: %s", MessageHelper.infoString( persister, id, getFactory() ) );
}
LoadEvent event = new LoadEvent(id, entityName, true, this);
fireLoad(event, LoadEventListener.IMMEDIATE_LOAD);
return event.getResult();
}
@Override
public Object internalLoad(String entityName, Serializable id, boolean eager, boolean nullable) throws HibernateException {
LoadEventListener.LoadType type = nullable
? LoadEventListener.INTERNAL_LOAD_NULLABLE
: eager
? LoadEventListener.INTERNAL_LOAD_EAGER
: LoadEventListener.INTERNAL_LOAD_LAZY;
LoadEvent event = new LoadEvent(id, entityName, true, this);
fireLoad( event, type );
if ( !nullable ) {
UnresolvableObjectException.throwIfNull( event.getResult(), id, entityName );
}
return event.getResult();
}
@Override
public Object load(Class entityClass, Serializable id, LockMode lockMode) throws HibernateException {
return this.byId( entityClass ).with( new LockOptions( lockMode ) ).getReference( id );
}
@Override
public Object load(Class entityClass, Serializable id, LockOptions lockOptions) throws HibernateException {
return this.byId( entityClass ).with( lockOptions ).getReference( id );
}
@Override
public Object load(String entityName, Serializable id, LockMode lockMode) throws HibernateException {
return this.byId( entityName ).with( new LockOptions( lockMode ) ).getReference( id );
}
@Override
public Object load(String entityName, Serializable id, LockOptions lockOptions) throws HibernateException {
return this.byId( entityName ).with( lockOptions ).getReference( id );
}
@Override
public Object get(Class entityClass, Serializable id, LockMode lockMode) throws HibernateException {
return this.byId( entityClass ).with( new LockOptions( lockMode ) ).load( id );
}
@Override
public Object get(Class entityClass, Serializable id, LockOptions lockOptions) throws HibernateException {
return this.byId( entityClass ).with( lockOptions ).load( id );
}
@Override
public Object get(String entityName, Serializable id, LockMode lockMode) throws HibernateException {
return this.byId( entityName ).with( new LockOptions( lockMode ) ).load( id );
}
@Override
public Object get(String entityName, Serializable id, LockOptions lockOptions) throws HibernateException {
return this.byId( entityName ).with( lockOptions ).load( id );
}
@Override
public IdentifierLoadAccessImpl byId(String entityName) {
return new IdentifierLoadAccessImpl( entityName );
}
@Override
public IdentifierLoadAccessImpl byId(Class entityClass) {
return new IdentifierLoadAccessImpl( entityClass );
}
@Override
public NaturalIdLoadAccess byNaturalId(String entityName) {
return new NaturalIdLoadAccessImpl( entityName );
}
@Override
public NaturalIdLoadAccess byNaturalId(Class entityClass) {
return new NaturalIdLoadAccessImpl( entityClass );
}
@Override
public SimpleNaturalIdLoadAccess bySimpleNaturalId(String entityName) {
return new SimpleNaturalIdLoadAccessImpl( entityName );
}
@Override
public SimpleNaturalIdLoadAccess bySimpleNaturalId(Class entityClass) {
return new SimpleNaturalIdLoadAccessImpl( entityClass );
}
private void fireLoad(LoadEvent event, LoadType loadType) {
errorIfClosed();
checkTransactionSynchStatus();
for ( LoadEventListener listener : listeners( EventType.LOAD ) ) {
listener.onLoad( event, loadType );
}
delayedAfterCompletion();
}
private void fireResolveNaturalId(ResolveNaturalIdEvent event) {
errorIfClosed();
checkTransactionSynchStatus();
for ( ResolveNaturalIdEventListener listener : listeners( EventType.RESOLVE_NATURAL_ID ) ) {
listener.onResolveNaturalId( event );
}
delayedAfterCompletion();
}
@Override
public void refresh(Object object) throws HibernateException {
refresh( null, object );
}
@Override
public void refresh(String entityName, Object object) throws HibernateException {
fireRefresh( new RefreshEvent( entityName, object, this ) );
}
@Override
public void refresh(Object object, LockMode lockMode) throws HibernateException {
fireRefresh( new RefreshEvent( object, lockMode, this ) );
}
@Override
public void refresh(Object object, LockOptions lockOptions) throws HibernateException {
refresh( null, object, lockOptions );
}
@Override
public void refresh(String entityName, Object object, LockOptions lockOptions) throws HibernateException {
fireRefresh( new RefreshEvent( entityName, object, lockOptions, this ) );
}
@Override
public void refresh(String entityName, Object object, Map refreshedAlready) throws HibernateException {
fireRefresh( refreshedAlready, new RefreshEvent( entityName, object, this ) );
}
private void fireRefresh(RefreshEvent event) {
errorIfClosed();
checkTransactionSynchStatus();
for ( RefreshEventListener listener : listeners( EventType.REFRESH ) ) {
listener.onRefresh( event );
}
delayedAfterCompletion();
}
private void fireRefresh(Map refreshedAlready, RefreshEvent event) {
errorIfClosed();
checkTransactionSynchStatus();
for ( RefreshEventListener listener : listeners( EventType.REFRESH ) ) {
listener.onRefresh( event, refreshedAlready );
}
delayedAfterCompletion();
}
@Override
public void replicate(Object obj, ReplicationMode replicationMode) throws HibernateException {
fireReplicate( new ReplicateEvent( obj, replicationMode, this ) );
}
@Override
public void replicate(String entityName, Object obj, ReplicationMode replicationMode)
throws HibernateException {
fireReplicate( new ReplicateEvent( entityName, obj, replicationMode, this ) );
}
private void fireReplicate(ReplicateEvent event) {
errorIfClosed();
checkTransactionSynchStatus();
for ( ReplicateEventListener listener : listeners( EventType.REPLICATE ) ) {
listener.onReplicate( event );
}
delayedAfterCompletion();
}
@Override
public void evict(Object object) throws HibernateException {
fireEvict( new EvictEvent( object, this ) );
}
private void fireEvict(EvictEvent event) {
errorIfClosed();
checkTransactionSynchStatus();
for ( EvictEventListener listener : listeners( EventType.EVICT ) ) {
listener.onEvict( event );
}
delayedAfterCompletion();
}
protected boolean autoFlushIfRequired(Set querySpaces) throws HibernateException {
errorIfClosed();
if ( ! isTransactionInProgress() ) {
return false;
}
AutoFlushEvent event = new AutoFlushEvent( querySpaces, this );
for ( AutoFlushEventListener listener : listeners( EventType.AUTO_FLUSH ) ) {
listener.onAutoFlush( event );
}
return event.isFlushRequired();
}
@Override
public boolean isDirty() throws HibernateException {
errorIfClosed();
checkTransactionSynchStatus();
LOG.debug( "Checking session dirtiness" );
if ( actionQueue.areInsertionsOrDeletionsQueued() ) {
LOG.debug( "Session dirty (scheduled updates and insertions)" );
return true;
}
DirtyCheckEvent event = new DirtyCheckEvent( this );
for ( DirtyCheckEventListener listener : listeners( EventType.DIRTY_CHECK ) ) {
listener.onDirtyCheck( event );
}
delayedAfterCompletion();
return event.isDirty();
}
@Override
public void flush() throws HibernateException {
errorIfClosed();
checkTransactionSynchStatus();
if ( persistenceContext.getCascadeLevel() > 0 ) {
throw new HibernateException("Flush during cascade is dangerous");
}
FlushEvent flushEvent = new FlushEvent( this );
for ( FlushEventListener listener : listeners( EventType.FLUSH ) ) {
listener.onFlush( flushEvent );
}
delayedAfterCompletion();
}
@Override
public void forceFlush(EntityEntry entityEntry) throws HibernateException {
errorIfClosed();
if ( LOG.isDebugEnabled() ) {
LOG.debugf( "Flushing to force deletion of re-saved object: %s",
MessageHelper.infoString( entityEntry.getPersister(), entityEntry.getId(), getFactory() ) );
}
if ( persistenceContext.getCascadeLevel() > 0 ) {
throw new ObjectDeletedException(
"deleted object would be re-saved by cascade (remove deleted object from associations)",
entityEntry.getId(),
entityEntry.getPersister().getEntityName()
);
}
flush();
}
@Override
public List list(String query, QueryParameters queryParameters) throws HibernateException {
errorIfClosed();
checkTransactionSynchStatus();
queryParameters.validateParameters();
HQLQueryPlan plan = queryParameters.getQueryPlan();
if (plan == null) {
plan = getHQLQueryPlan( query, false );
}
autoFlushIfRequired( plan.getQuerySpaces() );
List results = Collections.EMPTY_LIST;
boolean success = false;
dontFlushFromFind++;
try {
results = plan.performList( queryParameters, this );
success = true;
}
finally {
dontFlushFromFind--;
afterOperation(success);
delayedAfterCompletion();
}
return results;
}
@Override
public int executeUpdate(String query, QueryParameters queryParameters) throws HibernateException {
errorIfClosed();
checkTransactionSynchStatus();
queryParameters.validateParameters();
HQLQueryPlan plan = getHQLQueryPlan( query, false );
autoFlushIfRequired( plan.getQuerySpaces() );
boolean success = false;
int result = 0;
try {
result = plan.performExecuteUpdate( queryParameters, this );
success = true;
}
finally {
afterOperation(success);
delayedAfterCompletion();
}
return result;
}
@Override
public int executeNativeUpdate(NativeSQLQuerySpecification nativeQuerySpecification,
QueryParameters queryParameters) throws HibernateException {
errorIfClosed();
checkTransactionSynchStatus();
queryParameters.validateParameters();
NativeSQLQueryPlan plan = getNativeSQLQueryPlan( nativeQuerySpecification );
autoFlushIfRequired( plan.getCustomQuery().getQuerySpaces() );
boolean success = false;
int result = 0;
try {
result = plan.performExecuteUpdate(queryParameters, this);
success = true;
} finally {
afterOperation(success);
delayedAfterCompletion();
}
return result;
}
@Override
public Iterator iterate(String query, QueryParameters queryParameters) throws HibernateException {
errorIfClosed();
checkTransactionSynchStatus();
queryParameters.validateParameters();
HQLQueryPlan plan = getHQLQueryPlan( query, true );
autoFlushIfRequired( plan.getQuerySpaces() );
dontFlushFromFind++;
try {
return plan.performIterate( queryParameters, this );
}
finally {
delayedAfterCompletion();
dontFlushFromFind--;
}
}
@Override
public ScrollableResults scroll(String query, QueryParameters queryParameters) throws HibernateException {
errorIfClosed();
checkTransactionSynchStatus();
HQLQueryPlan plan = getHQLQueryPlan( query, false );
autoFlushIfRequired( plan.getQuerySpaces() );
dontFlushFromFind++;
try {
return plan.performScroll( queryParameters, this );
}
finally {
delayedAfterCompletion();
dontFlushFromFind--;
}
}
@Override
public Query createFilter(Object collection, String queryString) {
errorIfClosed();
checkTransactionSynchStatus();
CollectionFilterImpl filter = new CollectionFilterImpl(
queryString,
collection,
this,
getFilterQueryPlan( collection, queryString, null, false ).getParameterMetadata()
);
filter.setComment( queryString );
delayedAfterCompletion();
return filter;
}
@Override
public Query getNamedQuery(String queryName) throws MappingException {
errorIfClosed();
checkTransactionSynchStatus();
Query query = super.getNamedQuery( queryName );
delayedAfterCompletion();
return query;
}
@Override
public Object instantiate(String entityName, Serializable id) throws HibernateException {
return instantiate( factory.getEntityPersister( entityName ), id );
}
@Override
public Object instantiate(EntityPersister persister, Serializable id) throws HibernateException {
errorIfClosed();
checkTransactionSynchStatus();
Object result = interceptor.instantiate( persister.getEntityName(), persister.getEntityMetamodel().getEntityMode(), id );
if ( result == null ) {
result = persister.instantiate( id, this );
}
delayedAfterCompletion();
return result;
}
@Override
public void setFlushMode(FlushMode flushMode) {
errorIfClosed();
checkTransactionSynchStatus();
LOG.tracev( "Setting flush mode to: {0}", flushMode );
this.flushMode = flushMode;
}
@Override
public FlushMode getFlushMode() {
checkTransactionSynchStatus();
return flushMode;
}
@Override
public CacheMode getCacheMode() {
checkTransactionSynchStatus();
return cacheMode;
}
@Override
public void setCacheMode(CacheMode cacheMode) {
errorIfClosed();
checkTransactionSynchStatus();
LOG.tracev( "Setting cache mode to: {0}", cacheMode );
this.cacheMode= cacheMode;
}
@Override
public Transaction getTransaction() throws HibernateException {
errorIfClosed();
return transactionCoordinator.getTransaction();
}
@Override
public Transaction beginTransaction() throws HibernateException {
errorIfClosed();
Transaction result = getTransaction();
result.begin();
return result;
}
@Override
public EntityPersister getEntityPersister(final String entityName, final Object object) {
errorIfClosed();
if (entityName==null) {
return factory.getEntityPersister( guessEntityName( object ) );
}
else {
try {
return factory.getEntityPersister( entityName ).getSubclassEntityPersister( object, getFactory() );
}
catch( HibernateException e ) {
try {
return getEntityPersister( null, object );
}
catch( HibernateException e2 ) {
throw e;
}
}
}
}
@Override
public Serializable getIdentifier(Object object) throws HibernateException {
errorIfClosed();
checkTransactionSynchStatus();
if ( object instanceof HibernateProxy ) {
LazyInitializer li = ( (HibernateProxy) object ).getHibernateLazyInitializer();
if ( li.getSession() != this ) {
throw new TransientObjectException( "The proxy was not associated with this session" );
}
return li.getIdentifier();
}
else {
EntityEntry entry = persistenceContext.getEntry(object);
if ( entry == null ) {
throw new TransientObjectException( "The instance was not associated with this session" );
}
return entry.getId();
}
}
@Override
public Serializable getContextEntityIdentifier(Object object) {
errorIfClosed();
if ( object instanceof HibernateProxy ) {
return getProxyIdentifier( object );
}
else {
EntityEntry entry = persistenceContext.getEntry(object);
return entry != null ? entry.getId() : null;
}
}
private Serializable getProxyIdentifier(Object proxy) {
return ( (HibernateProxy) proxy ).getHibernateLazyInitializer().getIdentifier();
}
private FilterQueryPlan getFilterQueryPlan(
Object collection,
String filter,
QueryParameters parameters,
boolean shallow) throws HibernateException {
if ( collection == null ) {
throw new NullPointerException( "null collection passed to filter" );
}
CollectionEntry entry = persistenceContext.getCollectionEntryOrNull( collection );
final CollectionPersister roleBeforeFlush = (entry == null) ? null : entry.getLoadedPersister();
FilterQueryPlan plan = null;
if ( roleBeforeFlush == null ) {
flush();
entry = persistenceContext.getCollectionEntryOrNull( collection );
CollectionPersister roleAfterFlush = (entry == null) ? null : entry.getLoadedPersister();
if ( roleAfterFlush == null ) {
throw new QueryException( "The collection was unreferenced" );
}
plan = factory.getQueryPlanCache().getFilterQueryPlan( filter, roleAfterFlush.getRole(), shallow, getEnabledFilters() );
}
else {
plan = factory.getQueryPlanCache().getFilterQueryPlan( filter, roleBeforeFlush.getRole(), shallow, getEnabledFilters() );
if ( autoFlushIfRequired( plan.getQuerySpaces() ) ) {
entry = persistenceContext.getCollectionEntryOrNull( collection );
CollectionPersister roleAfterFlush = (entry == null) ? null : entry.getLoadedPersister();
if ( roleBeforeFlush != roleAfterFlush ) {
if ( roleAfterFlush == null ) {
throw new QueryException( "The collection was dereferenced" );
}
plan = factory.getQueryPlanCache().getFilterQueryPlan( filter, roleAfterFlush.getRole(), shallow, getEnabledFilters() );
}
}
}
if ( parameters != null ) {
parameters.getPositionalParameterValues()[0] = entry.getLoadedKey();
parameters.getPositionalParameterTypes()[0] = entry.getLoadedPersister().getKeyType();
}
return plan;
}
@Override
public List listFilter(Object collection, String filter, QueryParameters queryParameters)
throws HibernateException {
errorIfClosed();
checkTransactionSynchStatus();
FilterQueryPlan plan = getFilterQueryPlan( collection, filter, queryParameters, false );
List results = Collections.EMPTY_LIST;
boolean success = false;
dontFlushFromFind++;
try {
results = plan.performList( queryParameters, this );
success = true;
}
finally {
dontFlushFromFind--;
afterOperation(success);
delayedAfterCompletion();
}
return results;
}
@Override
public Iterator iterateFilter(Object collection, String filter, QueryParameters queryParameters)
throws HibernateException {
errorIfClosed();
checkTransactionSynchStatus();
FilterQueryPlan plan = getFilterQueryPlan( collection, filter, queryParameters, true );
Iterator itr = plan.performIterate( queryParameters, this );
delayedAfterCompletion();
return itr;
}
@Override
public Criteria createCriteria(Class persistentClass, String alias) {
errorIfClosed();
checkTransactionSynchStatus();
return new CriteriaImpl( persistentClass.getName(), alias, this );
}
@Override
public Criteria createCriteria(String entityName, String alias) {
errorIfClosed();
checkTransactionSynchStatus();
return new CriteriaImpl(entityName, alias, this);
}
@Override
public Criteria createCriteria(Class persistentClass) {
errorIfClosed();
checkTransactionSynchStatus();
return new CriteriaImpl( persistentClass.getName(), this );
}
@Override
public Criteria createCriteria(String entityName) {
errorIfClosed();
checkTransactionSynchStatus();
return new CriteriaImpl(entityName, this);
}
@Override
public ScrollableResults scroll(Criteria criteria, ScrollMode scrollMode) {
CriteriaImpl criteriaImpl = (CriteriaImpl) criteria;
errorIfClosed();
checkTransactionSynchStatus();
String entityName = criteriaImpl.getEntityOrClassName();
CriteriaLoader loader = new CriteriaLoader(
getOuterJoinLoadable(entityName),
factory,
criteriaImpl,
entityName,
getLoadQueryInfluencers()
);
autoFlushIfRequired( loader.getQuerySpaces() );
dontFlushFromFind++;
try {
return loader.scroll(this, scrollMode);
}
finally {
delayedAfterCompletion();
dontFlushFromFind--;
}
}
@Override
public List list(Criteria criteria) throws HibernateException {
CriteriaImpl criteriaImpl = (CriteriaImpl) criteria;
final NaturalIdLoadAccess naturalIdLoadAccess = this.tryNaturalIdLoadAccess( criteriaImpl );
if ( naturalIdLoadAccess != null ) {
return Arrays.asList( naturalIdLoadAccess.load() );
}
errorIfClosed();
checkTransactionSynchStatus();
String[] implementors = factory.getImplementors( criteriaImpl.getEntityOrClassName() );
int size = implementors.length;
CriteriaLoader[] loaders = new CriteriaLoader[size];
Set spaces = new HashSet();
for( int i=0; i <size; i++ ) {
loaders[i] = new CriteriaLoader(
getOuterJoinLoadable( implementors[i] ),
factory,
criteriaImpl,
implementors[i],
getLoadQueryInfluencers()
);
spaces.addAll( loaders[i].getQuerySpaces() );
}
autoFlushIfRequired(spaces);
List results = Collections.EMPTY_LIST;
dontFlushFromFind++;
boolean success = false;
try {
for( int i=0; i<size; i++ ) {
final List currentResults = loaders[i].list(this);
currentResults.addAll(results);
results = currentResults;
}
success = true;
}
finally {
dontFlushFromFind--;
afterOperation(success);
delayedAfterCompletion();
}
return results;
}
private NaturalIdLoadAccess tryNaturalIdLoadAccess(CriteriaImpl criteria) {
if ( !criteria.isLookupByNaturalKey() ) {
return null;
}
final String entityName = criteria.getEntityOrClassName();
final EntityPersister entityPersister = factory.getEntityPersister( entityName );
if ( !entityPersister.hasNaturalIdentifier() ) {
return null;
}
final CriterionEntry criterionEntry = (CriterionEntry) criteria.iterateExpressionEntries().next();
final NaturalIdentifier naturalIdentifier = (NaturalIdentifier) criterionEntry.getCriterion();
final Map<String, Object> naturalIdValues = naturalIdentifier.getNaturalIdValues();
final int[] naturalIdentifierProperties = entityPersister.getNaturalIdentifierProperties();
if ( naturalIdentifierProperties.length != naturalIdValues.size() ) {
return null;
}
final String[] propertyNames = entityPersister.getPropertyNames();
final NaturalIdLoadAccess naturalIdLoader = this.byNaturalId( entityName );
for ( int i = 0; i < naturalIdentifierProperties.length; i++ ) {
final String naturalIdProperty = propertyNames[naturalIdentifierProperties[i]];
final Object naturalIdValue = naturalIdValues.get( naturalIdProperty );
if ( naturalIdValue == null ) {
return null;
}
naturalIdLoader.using( naturalIdProperty, naturalIdValue );
}
LOG.warn( "Session.byNaturalId(" + entityName
+ ") should be used for naturalId queries instead of Restrictions.naturalId() from a Criteria" );
return naturalIdLoader;
}
private OuterJoinLoadable getOuterJoinLoadable(String entityName) throws MappingException {
EntityPersister persister = factory.getEntityPersister(entityName);
if ( !(persister instanceof OuterJoinLoadable) ) {
throw new MappingException( "class persister is not OuterJoinLoadable: " + entityName );
}
return ( OuterJoinLoadable ) persister;
}
@Override
public boolean contains(Object object) {
errorIfClosed();
checkTransactionSynchStatus();
if ( object instanceof HibernateProxy ) {
LazyInitializer li = ( (HibernateProxy) object ).getHibernateLazyInitializer();
if ( li.isUninitialized() ) {
return li.getSession()==this;
}
else {
object = li.getImplementation();
}
}
EntityEntry entry = persistenceContext.getEntry( object );
delayedAfterCompletion();
return entry != null && entry.getStatus() != Status.DELETED && entry.getStatus() != Status.GONE;
}
@Override
public Query createQuery(String queryString) {
errorIfClosed();
checkTransactionSynchStatus();
return super.createQuery( queryString );
}
@Override
public SQLQuery createSQLQuery(String sql) {
errorIfClosed();
checkTransactionSynchStatus();
return super.createSQLQuery( sql );
}
@Override
public ProcedureCall createStoredProcedureCall(String procedureName) {
errorIfClosed();
checkTransactionSynchStatus();
return super.createStoredProcedureCall( procedureName );
}
@Override
public ProcedureCall createStoredProcedureCall(String procedureName, String... resultSetMappings) {
errorIfClosed();
checkTransactionSynchStatus();
return super.createStoredProcedureCall( procedureName, resultSetMappings );
}
@Override
public ProcedureCall createStoredProcedureCall(String procedureName, Class... resultClasses) {
errorIfClosed();
checkTransactionSynchStatus();
return super.createStoredProcedureCall( procedureName, resultClasses );
}
@Override
public ScrollableResults scrollCustomQuery(CustomQuery customQuery, QueryParameters queryParameters)
throws HibernateException {
errorIfClosed();
checkTransactionSynchStatus();
if ( LOG.isTraceEnabled() ) {
LOG.tracev( "Scroll SQL query: {0}", customQuery.getSQL() );
}
CustomLoader loader = new CustomLoader( customQuery, getFactory() );
autoFlushIfRequired( loader.getQuerySpaces() );
dontFlushFromFind++;
try {
return loader.scroll(queryParameters, this);
}
finally {
delayedAfterCompletion();
dontFlushFromFind--;
}
}
@Override
public List listCustomQuery(CustomQuery customQuery, QueryParameters queryParameters)
throws HibernateException {
errorIfClosed();
checkTransactionSynchStatus();
if ( LOG.isTraceEnabled() ) {
LOG.tracev( "SQL query: {0}", customQuery.getSQL() );
}
CustomLoader loader = new CustomLoader( customQuery, getFactory() );
autoFlushIfRequired( loader.getQuerySpaces() );
dontFlushFromFind++;
boolean success = false;
try {
List results = loader.list(this, queryParameters);
success = true;
return results;
}
finally {
dontFlushFromFind--;
delayedAfterCompletion();
afterOperation(success);
}
}
@Override
public SessionFactoryImplementor getSessionFactory() {
checkTransactionSynchStatus();
return factory;
}
@Override
public void initializeCollection(PersistentCollection collection, boolean writing)
throws HibernateException {
errorIfClosed();
checkTransactionSynchStatus();
InitializeCollectionEvent event = new InitializeCollectionEvent( collection, this );
for ( InitializeCollectionEventListener listener : listeners( EventType.INIT_COLLECTION ) ) {
listener.onInitializeCollection( event );
}
delayedAfterCompletion();
}
@Override
public String bestGuessEntityName(Object object) {
if (object instanceof HibernateProxy) {
LazyInitializer initializer = ( ( HibernateProxy ) object ).getHibernateLazyInitializer();
if ( initializer.isUninitialized() ) {
return initializer.getEntityName();
}
object = initializer.getImplementation();
}
EntityEntry entry = persistenceContext.getEntry(object);
if (entry==null) {
return guessEntityName(object);
}
else {
return entry.getPersister().getEntityName();
}
}
@Override
public String getEntityName(Object object) {
errorIfClosed();
checkTransactionSynchStatus();
if (object instanceof HibernateProxy) {
if ( !persistenceContext.containsProxy( object ) ) {
throw new TransientObjectException("proxy was not associated with the session");
}
object = ( (HibernateProxy) object ).getHibernateLazyInitializer().getImplementation();
}
EntityEntry entry = persistenceContext.getEntry(object);
if ( entry == null ) {
throwTransientObjectException( object );
}
return entry.getPersister().getEntityName();
}
private void throwTransientObjectException(Object object) throws HibernateException {
throw new TransientObjectException(
"object references an unsaved transient instance - save the transient instance before flushing: " +
guessEntityName(object)
);
}
@Override
public String guessEntityName(Object object) throws HibernateException {
errorIfClosed();
return entityNameResolver.resolveEntityName( object );
}
@Override
public void cancelQuery() throws HibernateException {
errorIfClosed();
getTransactionCoordinator().getJdbcCoordinator().cancelLastQuery();
}
@Override
public Interceptor getInterceptor() {
checkTransactionSynchStatus();
return interceptor;
}
@Override
public int getDontFlushFromFind() {
return dontFlushFromFind;
}
@Override
public String toString() {
StringBuilder buf = new StringBuilder(500)
.append( "SessionImpl(" );
if ( !isClosed() ) {
buf.append(persistenceContext)
.append(";")
.append(actionQueue);
}
else {
buf.append("<closed>");
}
return buf.append(')').toString();
}
@Override
public ActionQueue getActionQueue() {
errorIfClosed();
checkTransactionSynchStatus();
return actionQueue;
}
@Override
public PersistenceContext getPersistenceContext() {
errorIfClosed();
checkTransactionSynchStatus();
return persistenceContext;
}
@Override
public SessionStatistics getStatistics() {
checkTransactionSynchStatus();
return new SessionStatisticsImpl(this);
}
@Override
public boolean isEventSource() {
checkTransactionSynchStatus();
return true;
}
@Override
public boolean isDefaultReadOnly() {
return persistenceContext.isDefaultReadOnly();
}
@Override
public void setDefaultReadOnly(boolean defaultReadOnly) {
persistenceContext.setDefaultReadOnly( defaultReadOnly );
}
@Override
public boolean isReadOnly(Object entityOrProxy) {
errorIfClosed();
checkTransactionSynchStatus();
return persistenceContext.isReadOnly( entityOrProxy );
}
@Override
public void setReadOnly(Object entity, boolean readOnly) {
errorIfClosed();
checkTransactionSynchStatus();
persistenceContext.setReadOnly( entity, readOnly );
}
@Override
public void doWork(final Work work) throws HibernateException {
WorkExecutorVisitable<Void> realWork = new WorkExecutorVisitable<Void>() {
@Override
public Void accept(WorkExecutor<Void> workExecutor, Connection connection) throws SQLException {
workExecutor.executeWork( work, connection );
return null;
}
};
doWork( realWork );
}
@Override
public <T> T doReturningWork(final ReturningWork<T> work) throws HibernateException {
WorkExecutorVisitable<T> realWork = new WorkExecutorVisitable<T>() {
@Override
public T accept(WorkExecutor<T> workExecutor, Connection connection) throws SQLException {
return workExecutor.executeReturningWork( work, connection );
}
};
return doWork( realWork );
}
private <T> T doWork(WorkExecutorVisitable<T> work) throws HibernateException {
return transactionCoordinator.getJdbcCoordinator().coordinateWork( work );
}
@Override
public void afterScrollOperation() {
}
@Override
public TransactionCoordinator getTransactionCoordinator() {
errorIfClosed();
return transactionCoordinator;
}
@Override
public LoadQueryInfluencers getLoadQueryInfluencers() {
return loadQueryInfluencers;
}
@Override
public Filter getEnabledFilter(String filterName) {
checkTransactionSynchStatus();
return loadQueryInfluencers.getEnabledFilter( filterName );
}
@Override
public Filter enableFilter(String filterName) {
errorIfClosed();
checkTransactionSynchStatus();
return loadQueryInfluencers.enableFilter( filterName );
}
@Override
public void disableFilter(String filterName) {
errorIfClosed();
checkTransactionSynchStatus();
loadQueryInfluencers.disableFilter( filterName );
}
@Override
public Object getFilterParameterValue(String filterParameterName) {
errorIfClosed();
checkTransactionSynchStatus();
return loadQueryInfluencers.getFilterParameterValue( filterParameterName );
}
@Override
public Type getFilterParameterType(String filterParameterName) {
errorIfClosed();
checkTransactionSynchStatus();
return loadQueryInfluencers.getFilterParameterType( filterParameterName );
}
@Override
public Map getEnabledFilters() {
errorIfClosed();
checkTransactionSynchStatus();
return loadQueryInfluencers.getEnabledFilters();
}
@Override
public String getFetchProfile() {
checkTransactionSynchStatus();
return loadQueryInfluencers.getInternalFetchProfile();
}
@Override
public void setFetchProfile(String fetchProfile) {
errorIfClosed();
checkTransactionSynchStatus();
loadQueryInfluencers.setInternalFetchProfile( fetchProfile );
}
@Override
public boolean isFetchProfileEnabled(String name) throws UnknownProfileException {
return loadQueryInfluencers.isFetchProfileEnabled( name );
}
@Override
public void enableFetchProfile(String name) throws UnknownProfileException {
loadQueryInfluencers.enableFetchProfile( name );
}
@Override
public void disableFetchProfile(String name) throws UnknownProfileException {
loadQueryInfluencers.disableFetchProfile( name );
}
private void checkTransactionSynchStatus() {
pulseTransactionCoordinator();
delayedAfterCompletion();
}
private void pulseTransactionCoordinator() {
if ( !isClosed() ) {
transactionCoordinator.pulse();
}
}
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
LOG.trace( "Deserializing session" );
ois.defaultReadObject();
entityNameResolver = new CoordinatingEntityNameResolver();
connectionReleaseMode = ConnectionReleaseMode.parse( ( String ) ois.readObject() );
autoClear = ois.readBoolean();
autoJoinTransactions = ois.readBoolean();
flushMode = FlushMode.valueOf( ( String ) ois.readObject() );
cacheMode = CacheMode.valueOf( ( String ) ois.readObject() );
flushBeforeCompletionEnabled = ois.readBoolean();
autoCloseSessionEnabled = ois.readBoolean();
interceptor = ( Interceptor ) ois.readObject();
factory = SessionFactoryImpl.deserialize( ois );
sessionOwner = ( SessionOwner ) ois.readObject();
transactionCoordinator = TransactionCoordinatorImpl.deserialize( ois, this );
persistenceContext = StatefulPersistenceContext.deserialize( ois, this );
actionQueue = ActionQueue.deserialize( ois, this );
loadQueryInfluencers = (LoadQueryInfluencers) ois.readObject();
for ( String filterName : loadQueryInfluencers.getEnabledFilterNames() ) {
((FilterImpl) loadQueryInfluencers.getEnabledFilter( filterName )).afterDeserialize( factory );
}
}
private void writeObject(ObjectOutputStream oos) throws IOException {
if ( ! transactionCoordinator.getJdbcCoordinator().isReadyForSerialization() ) {
throw new IllegalStateException( "Cannot serialize a session while connected" );
}
LOG.trace( "Serializing session" );
oos.defaultWriteObject();
oos.writeObject( connectionReleaseMode.toString() );
oos.writeBoolean( autoClear );
oos.writeBoolean( autoJoinTransactions );
oos.writeObject( flushMode.toString() );
oos.writeObject( cacheMode.name() );
oos.writeBoolean( flushBeforeCompletionEnabled );
oos.writeBoolean( autoCloseSessionEnabled );
oos.writeObject( interceptor );
factory.serialize( oos );
oos.writeObject( sessionOwner );
transactionCoordinator.serialize( oos );
persistenceContext.serialize( oos );
actionQueue.serialize( oos );
oos.writeObject( loadQueryInfluencers );
}
@Override
public TypeHelper getTypeHelper() {
return getSessionFactory().getTypeHelper();
}
@Override
public LobHelper getLobHelper() {
if ( lobHelper == null ) {
lobHelper = new LobHelperImpl( this );
}
return lobHelper;
}
private transient LobHelperImpl lobHelper;
private static class LobHelperImpl implements LobHelper {
private final SessionImpl session;
private LobHelperImpl(SessionImpl session) {
this.session = session;
}
@Override
public Blob createBlob(byte[] bytes) {
return lobCreator().createBlob( bytes );
}
private LobCreator lobCreator() {
return NonContextualLobCreator.INSTANCE;
}
@Override
public Blob createBlob(InputStream stream, long length) {
return lobCreator().createBlob( stream, length );
}
@Override
public Clob createClob(String string) {
return lobCreator().createClob( string );
}
@Override
public Clob createClob(Reader reader, long length) {
return lobCreator().createClob( reader, length );
}
@Override
public NClob createNClob(String string) {
return lobCreator().createNClob( string );
}
@Override
public NClob createNClob(Reader reader, long length) {
return lobCreator().createNClob( reader, length );
}
}
private static class SharedSessionBuilderImpl extends SessionFactoryImpl.SessionBuilderImpl implements SharedSessionBuilder {
private final SessionImpl session;
private boolean shareTransactionContext;
private SharedSessionBuilderImpl(SessionImpl session) {
super( session.factory );
this.session = session;
super.owner( session.sessionOwner );
super.tenantIdentifier( session.getTenantIdentifier() );
}
@Override
public SessionBuilder tenantIdentifier(String tenantIdentifier) {
throw new SessionException( "Cannot redefine tenant identifier on child session" );
}
@Override
protected TransactionCoordinatorImpl getTransactionCoordinator() {
return shareTransactionContext ? session.transactionCoordinator : super.getTransactionCoordinator();
}
@Override
protected ActionQueue.TransactionCompletionProcesses getTransactionCompletionProcesses() {
return shareTransactionContext ?
session.getActionQueue().getTransactionCompletionProcesses() :
super.getTransactionCompletionProcesses();
}
@Override
public SharedSessionBuilder interceptor() {
return interceptor( session.interceptor );
}
@Override
public SharedSessionBuilder connection() {
this.shareTransactionContext = true;
return this;
}
@Override
public SharedSessionBuilder connectionReleaseMode() {
return connectionReleaseMode( session.connectionReleaseMode );
}
@Override
public SharedSessionBuilder autoJoinTransactions() {
return autoJoinTransactions( session.autoJoinTransactions );
}
@Override
public SharedSessionBuilder autoClose() {
return autoClose( session.autoCloseSessionEnabled );
}
@Override
public SharedSessionBuilder flushBeforeCompletion() {
return flushBeforeCompletion( session.flushBeforeCompletionEnabled );
}
@Override
@Deprecated
public SharedSessionBuilder transactionContext() {
return connection();
}
@Override
public SharedSessionBuilder interceptor(Interceptor interceptor) {
return (SharedSessionBuilder) super.interceptor( interceptor );
}
@Override
public SharedSessionBuilder noInterceptor() {
return (SharedSessionBuilder) super.noInterceptor();
}
@Override
public SharedSessionBuilder connection(Connection connection) {
return (SharedSessionBuilder) super.connection( connection );
}
@Override
public SharedSessionBuilder connectionReleaseMode(ConnectionReleaseMode connectionReleaseMode) {
return (SharedSessionBuilder) super.connectionReleaseMode( connectionReleaseMode );
}
@Override
public SharedSessionBuilder autoJoinTransactions(boolean autoJoinTransactions) {
return (SharedSessionBuilder) super.autoJoinTransactions( autoJoinTransactions );
}
@Override
public SharedSessionBuilder autoClose(boolean autoClose) {
return (SharedSessionBuilder) super.autoClose( autoClose );
}
@Override
public SharedSessionBuilder flushBeforeCompletion(boolean flushBeforeCompletion) {
return (SharedSessionBuilder) super.flushBeforeCompletion( flushBeforeCompletion );
}
@Override
public SharedSessionBuilder eventListeners(SessionEventListener... listeners) {
super.eventListeners( listeners );
return this;
}
@Override
public SessionBuilder clearEventListeners() {
super.clearEventListeners();
return this;
}
}
private class CoordinatingEntityNameResolver implements EntityNameResolver {
@Override
public String resolveEntityName(Object entity) {
String entityName = interceptor.getEntityName( entity );
if ( entityName != null ) {
return entityName;
}
for ( EntityNameResolver resolver : factory.iterateEntityNameResolvers() ) {
entityName = resolver.resolveEntityName( entity );
if ( entityName != null ) {
break;
}
}
if ( entityName != null ) {
return entityName;
}
return entity.getClass().getName();
}
}
private class LockRequestImpl implements LockRequest {
private final LockOptions lockOptions;
private LockRequestImpl(LockOptions lo) {
lockOptions = new LockOptions();
LockOptions.copy(lo, lockOptions);
}
@Override
public LockMode getLockMode() {
return lockOptions.getLockMode();
}
@Override
public LockRequest setLockMode(LockMode lockMode) {
lockOptions.setLockMode(lockMode);
return this;
}
@Override
public int getTimeOut() {
return lockOptions.getTimeOut();
}
@Override
public LockRequest setTimeOut(int timeout) {
lockOptions.setTimeOut(timeout);
return this;
}
@Override
public boolean getScope() {
return lockOptions.getScope();
}
@Override
public LockRequest setScope(boolean scope) {
lockOptions.setScope(scope);
return this;
}
@Override
public void lock(String entityName, Object object) throws HibernateException {
fireLock( entityName, object, lockOptions );
}
@Override
public void lock(Object object) throws HibernateException {
fireLock( object, lockOptions );
}
}
private class IdentifierLoadAccessImpl implements IdentifierLoadAccess {
private final EntityPersister entityPersister;
private LockOptions lockOptions;
private IdentifierLoadAccessImpl(EntityPersister entityPersister) {
this.entityPersister = entityPersister;
}
private IdentifierLoadAccessImpl(String entityName) {
this( locateEntityPersister( entityName ) );
}
private IdentifierLoadAccessImpl(Class entityClass) {
this( entityClass.getName() );
}
@Override
public final IdentifierLoadAccessImpl with(LockOptions lockOptions) {
this.lockOptions = lockOptions;
return this;
}
@Override
public final Object getReference(Serializable id) {
if ( this.lockOptions != null ) {
LoadEvent event = new LoadEvent( id, entityPersister.getEntityName(), lockOptions, SessionImpl.this );
fireLoad( event, LoadEventListener.LOAD );
return event.getResult();
}
LoadEvent event = new LoadEvent( id, entityPersister.getEntityName(), false, SessionImpl.this );
boolean success = false;
try {
fireLoad( event, LoadEventListener.LOAD );
if ( event.getResult() == null ) {
getFactory().getEntityNotFoundDelegate().handleEntityNotFound( entityPersister.getEntityName(), id );
}
success = true;
return event.getResult();
}
finally {
afterOperation( success );
}
}
@Override
public final Object load(Serializable id) {
if ( this.lockOptions != null ) {
LoadEvent event = new LoadEvent( id, entityPersister.getEntityName(), lockOptions, SessionImpl.this );
fireLoad( event, LoadEventListener.GET );
return event.getResult();
}
LoadEvent event = new LoadEvent( id, entityPersister.getEntityName(), false, SessionImpl.this );
boolean success = false;
try {
fireLoad( event, LoadEventListener.GET );
success = true;
}
catch (ObjectNotFoundException e) {
}
finally {
afterOperation( success );
}
return event.getResult();
}
}
private EntityPersister locateEntityPersister(String entityName) {
final EntityPersister entityPersister = factory.getEntityPersister( entityName );
if ( entityPersister == null ) {
throw new HibernateException( "Unable to locate persister: " + entityName );
}
return entityPersister;
}
private abstract class BaseNaturalIdLoadAccessImpl {
private final EntityPersister entityPersister;
private LockOptions lockOptions;
private boolean synchronizationEnabled = true;
private BaseNaturalIdLoadAccessImpl(EntityPersister entityPersister) {
this.entityPersister = entityPersister;
if ( ! entityPersister.hasNaturalIdentifier() ) {
throw new HibernateException(
String.format( "Entity [%s] did not define a natural id", entityPersister.getEntityName() )
);
}
}
private BaseNaturalIdLoadAccessImpl(String entityName) {
this( locateEntityPersister( entityName ) );
}
private BaseNaturalIdLoadAccessImpl(Class entityClass) {
this( entityClass.getName() );
}
public BaseNaturalIdLoadAccessImpl with(LockOptions lockOptions) {
this.lockOptions = lockOptions;
return this;
}
protected void synchronizationEnabled(boolean synchronizationEnabled) {
this.synchronizationEnabled = synchronizationEnabled;
}
protected final Serializable resolveNaturalId(Map<String, Object> naturalIdParameters) {
performAnyNeededCrossReferenceSynchronizations();
final ResolveNaturalIdEvent event =
new ResolveNaturalIdEvent( naturalIdParameters, entityPersister, SessionImpl.this );
fireResolveNaturalId( event );
if ( event.getEntityId() == PersistenceContext.NaturalIdHelper.INVALID_NATURAL_ID_REFERENCE ) {
return null;
}
else {
return event.getEntityId();
}
}
protected void performAnyNeededCrossReferenceSynchronizations() {
if ( ! synchronizationEnabled ) {
return;
}
if ( entityPersister.getEntityMetamodel().hasImmutableNaturalId() ) {
return;
}
if ( ! isTransactionInProgress() ) {
return;
}
final boolean debugEnabled = LOG.isDebugEnabled();
for ( Serializable pk : getPersistenceContext().getNaturalIdHelper().getCachedPkResolutions( entityPersister ) ) {
final EntityKey entityKey = generateEntityKey( pk, entityPersister );
final Object entity = getPersistenceContext().getEntity( entityKey );
final EntityEntry entry = getPersistenceContext().getEntry( entity );
if ( entry == null ) {
if ( debugEnabled ) {
LOG.debug(
"Cached natural-id/pk resolution linked to null EntityEntry in persistence context : "
+ MessageHelper.infoString( entityPersister, pk, getFactory() )
);
}
continue;
}
if ( !entry.requiresDirtyCheck( entity ) ) {
continue;
}
if ( entry.getStatus() != Status.MANAGED ) {
continue;
}
getPersistenceContext().getNaturalIdHelper().handleSynchronization(
entityPersister,
pk,
entity
);
}
}
protected final IdentifierLoadAccess getIdentifierLoadAccess() {
final IdentifierLoadAccessImpl identifierLoadAccess = new IdentifierLoadAccessImpl( entityPersister );
if ( this.lockOptions != null ) {
identifierLoadAccess.with( lockOptions );
}
return identifierLoadAccess;
}
protected EntityPersister entityPersister() {
return entityPersister;
}
}
private class NaturalIdLoadAccessImpl extends BaseNaturalIdLoadAccessImpl implements NaturalIdLoadAccess {
private final Map<String, Object> naturalIdParameters = new LinkedHashMap<String, Object>();
private NaturalIdLoadAccessImpl(EntityPersister entityPersister) {
super(entityPersister);
}
private NaturalIdLoadAccessImpl(String entityName) {
this( locateEntityPersister( entityName ) );
}
private NaturalIdLoadAccessImpl(Class entityClass) {
this( entityClass.getName() );
}
@Override
public NaturalIdLoadAccessImpl with(LockOptions lockOptions) {
return (NaturalIdLoadAccessImpl) super.with( lockOptions );
}
@Override
public NaturalIdLoadAccess using(String attributeName, Object value) {
naturalIdParameters.put( attributeName, value );
return this;
}
@Override
public NaturalIdLoadAccessImpl setSynchronizationEnabled(boolean synchronizationEnabled) {
super.synchronizationEnabled( synchronizationEnabled );
return this;
}
@Override
public final Object getReference() {
final Serializable entityId = resolveNaturalId( this.naturalIdParameters );
if ( entityId == null ) {
return null;
}
return this.getIdentifierLoadAccess().getReference( entityId );
}
@Override
public final Object load() {
final Serializable entityId = resolveNaturalId( this.naturalIdParameters );
if ( entityId == null ) {
return null;
}
try {
return this.getIdentifierLoadAccess().load( entityId );
}
catch (EntityNotFoundException enf) {
}
catch (ObjectNotFoundException nf) {
}
return null;
}
}
private class SimpleNaturalIdLoadAccessImpl extends BaseNaturalIdLoadAccessImpl implements SimpleNaturalIdLoadAccess {
private final String naturalIdAttributeName;
private SimpleNaturalIdLoadAccessImpl(EntityPersister entityPersister) {
super(entityPersister);
if ( entityPersister.getNaturalIdentifierProperties().length != 1 ) {
throw new HibernateException(
String.format( "Entity [%s] did not define a simple natural id", entityPersister.getEntityName() )
);
}
final int naturalIdAttributePosition = entityPersister.getNaturalIdentifierProperties()[0];
this.naturalIdAttributeName = entityPersister.getPropertyNames()[ naturalIdAttributePosition ];
}
private SimpleNaturalIdLoadAccessImpl(String entityName) {
this( locateEntityPersister( entityName ) );
}
private SimpleNaturalIdLoadAccessImpl(Class entityClass) {
this( entityClass.getName() );
}
@Override
public final SimpleNaturalIdLoadAccessImpl with(LockOptions lockOptions) {
return (SimpleNaturalIdLoadAccessImpl) super.with( lockOptions );
}
private Map<String, Object> getNaturalIdParameters(Object naturalIdValue) {
return Collections.singletonMap( naturalIdAttributeName, naturalIdValue );
}
@Override
public SimpleNaturalIdLoadAccessImpl setSynchronizationEnabled(boolean synchronizationEnabled) {
super.synchronizationEnabled( synchronizationEnabled );
return this;
}
@Override
public Object getReference(Object naturalIdValue) {
final Serializable entityId = resolveNaturalId( getNaturalIdParameters( naturalIdValue ) );
if ( entityId == null ) {
return null;
}
return this.getIdentifierLoadAccess().getReference( entityId );
}
@Override
public Object load(Object naturalIdValue) {
final Serializable entityId = resolveNaturalId( getNaturalIdParameters( naturalIdValue ) );
if ( entityId == null ) {
return null;
}
try {
return this.getIdentifierLoadAccess().load( entityId );
}
catch (EntityNotFoundException enf) {
}
catch (ObjectNotFoundException nf) {
}
return null;
}
}
}