@Override public void replaceDelayedEntityIdentityInsertKeys(EntityKey oldKey, Serializable generatedId) { final Object entity = entitiesByKey.remove( oldKey ); final EntityEntry oldEntry = entityEntryContext.removeEntityEntry( entity ); parentsByChild.clear(); final EntityKey newKey = session.generateEntityKey( generatedId, oldEntry.getPersister() ); addEntity( newKey, entity ); addEntry( entity, oldEntry.getStatus(), oldEntry.getLoadedState(), oldEntry.getRowId(), generatedId, oldEntry.getVersion(), oldEntry.getLockMode(), oldEntry.isExistsInDatabase(), oldEntry.getPersister(), oldEntry.isBeingReplicated(), oldEntry.isLoadedWithLazyPropertiesUnfetched() ); }
/** * PostLoad cannot occur during initializeEntity, as that call occurs *before* * the Set collections are added to the persistence context by Loader. * Without the split, LazyInitializationExceptions can occur in the Entity's * postLoad if it acts upon the collection. * * HHH-6043 * * @param entity The entity * @param session The Session * @param postLoadEvent The (re-used) post-load event */ public static void postLoad( final Object entity, final SessionImplementor session, final PostLoadEvent postLoadEvent) { if ( session.isEventSource() ) { final PersistenceContext persistenceContext = session.getPersistenceContext(); final EntityEntry entityEntry = persistenceContext.getEntry( entity ); postLoadEvent.setEntity( entity ).setId( entityEntry.getId() ).setPersister( entityEntry.getPersister() ); final EventListenerGroup<PostLoadEventListener> listenerGroup = session.getFactory() .getServiceRegistry() .getService( EventListenerRegistry.class ) .getEventListenerGroup( EventType.POST_LOAD ); for ( PostLoadEventListener listener : listenerGroup.listeners() ) { listener.onPostLoad( postLoadEvent ); } } }
/** * Retrieve the associated EntityEntry for the entity * * @param entity The entity to retrieve the EntityEntry for * * @return The associated EntityEntry */ public EntityEntry getEntityEntry(Object entity) { // essentially resolve the entity to a ManagedEntity... final ManagedEntity managedEntity; if ( ManagedEntity.class.isInstance( entity ) ) { managedEntity = (ManagedEntity) entity; } else if ( nonEnhancedEntityXref == null ) { managedEntity = null; } else { managedEntity = nonEnhancedEntityXref.get( entity ); } // and get/return the EntityEntry from the ManagedEntry return managedEntity == null ? null : managedEntity.$$_hibernate_getEntityEntry(); }
/** * The main bugaboo with IdentityMap that warranted this class in the first place. * * Return an array of all the entity/EntityEntry pairs in this context. The array is to make sure * that the iterators built off of it are safe from concurrency/reentrancy * * @return The safe array */ public Map.Entry<Object, EntityEntry>[] reentrantSafeEntityEntries() { if ( dirty ) { reentrantSafeEntries = new EntityEntryCrossRefImpl[count]; int i = 0; ManagedEntity managedEntity = head; while ( managedEntity != null ) { reentrantSafeEntries[i++] = new EntityEntryCrossRefImpl( managedEntity.$$_hibernate_getEntityInstance(), managedEntity.$$_hibernate_getEntityEntry() ); managedEntity = managedEntity.$$_hibernate_getNextManagedEntity(); } dirty = false; } return reentrantSafeEntries; }
@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 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 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 String bestGuessEntityName(Object object) { if (object instanceof HibernateProxy) { LazyInitializer initializer = ( ( HibernateProxy ) object ).getHibernateLazyInitializer(); // it is possible for this method to be called during flush processing, // so make certain that we do not accidentally initialize an uninitialized proxy 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(); }
protected Serializable performSaveOrUpdate(SaveOrUpdateEvent event) { // this implementation is supposed to tolerate incorrect unsaved-value // mappings, for the purpose of backward-compatibility EntityEntry entry = event.getSession().getPersistenceContext().getEntry( event.getEntity() ); if ( entry!=null ) { if ( entry.getStatus()== Status.DELETED ) { throw new ObjectDeletedException( "deleted instance passed to update()", null, event.getEntityName() ); } else { return entityIsPersistent(event); } } else { entityIsDetached(event); return null; } }
protected void cascadeBeforeDelete( EventSource session, EntityPersister persister, Object entity, EntityEntry entityEntry, Set transientEntities) throws HibernateException { CacheMode cacheMode = session.getCacheMode(); session.setCacheMode( CacheMode.GET ); session.getPersistenceContext().incrementCascadeLevel(); try { // cascade-delete to collections BEFORE the collection owner is deleted new Cascade( CascadingActions.DELETE, CascadePoint.AFTER_INSERT_BEFORE_DELETE, session ).cascade( persister, entity, transientEntities ); } finally { session.getPersistenceContext().decrementCascadeLevel(); session.setCacheMode( cacheMode ); } }
private Object[] getValues(Object entity, EntityEntry entry, boolean mightBeDirty, SessionImplementor session) { final Object[] loadedState = entry.getLoadedState(); final Status status = entry.getStatus(); final EntityPersister persister = entry.getPersister(); final Object[] values; if ( status == Status.DELETED ) { //grab its state saved at deletion values = entry.getDeletedState(); } else if ( !mightBeDirty && loadedState != null ) { values = loadedState; } else { checkId( entity, persister, entry.getId(), session ); // grab its current state values = persister.getPropertyValues( entity ); checkNaturalId( persister, entry, values, loadedState, session ); } return values; }
protected boolean handleInterception(FlushEntityEvent event) { SessionImplementor session = event.getSession(); EntityEntry entry = event.getEntityEntry(); EntityPersister persister = entry.getPersister(); Object entity = event.getEntity(); //give the Interceptor a chance to modify property values final Object[] values = event.getPropertyValues(); final boolean intercepted = invokeInterceptor( session, entity, entry, values, persister ); //now we might need to recalculate the dirtyProperties array if ( intercepted && event.isDirtyCheckPossible() && !event.isDirtyCheckHandledByInterceptor() ) { int[] dirtyProperties; if ( event.hasDatabaseSnapshot() ) { dirtyProperties = persister.findModified( event.getDatabaseSnapshot(), values, entity, session ); } else { dirtyProperties = persister.findDirty( values, entry.getLoadedState(), entity, session ); } event.setDirtyProperties( dirtyProperties ); } return intercepted; }
/** * The given save-update event named a transient entity. * <p/> * Here, we will perform the save processing. * * @param event The save event to be handled. * * @return The entity's identifier after saving. */ protected Serializable entityIsTransient(SaveOrUpdateEvent event) { LOG.trace( "Saving transient instance" ); final EventSource source = event.getSession(); EntityEntry entityEntry = event.getEntry(); if ( entityEntry != null ) { if ( entityEntry.getStatus() == Status.DELETED ) { source.forceFlush( entityEntry ); } else { throw new AssertionFailure( "entity was persistent" ); } } Serializable id = saveWithGeneratedOrRequestedId( event ); source.getPersistenceContext().reassociateProxy( event.getObject(), id ); return id; }
/** * process cascade save/update at the start of a flush to discover * any newly referenced entity that must be passed to saveOrUpdate(), * and also apply orphan delete */ private void prepareEntityFlushes(EventSource session, PersistenceContext persistenceContext) throws HibernateException { LOG.debug( "Processing flush-time cascades" ); final Object anything = getAnything(); //safe from concurrent modification because of how concurrentEntries() is implemented on IdentityMap for ( Map.Entry<Object,EntityEntry> me : persistenceContext.reentrantSafeEntityEntries() ) { // for ( Map.Entry me : IdentityMap.concurrentEntries( persistenceContext.getEntityEntries() ) ) { EntityEntry entry = (EntityEntry) me.getValue(); Status status = entry.getStatus(); if ( status == Status.MANAGED || status == Status.SAVING || status == Status.READ_ONLY ) { cascadeOnFlush( session, entry.getPersister(), me.getKey(), anything ); } } }
/** * Sets the target object to read-write, allowing Hibernate to dirty check it and auto-flush changes. * * @see #setObjectToReadyOnly(Object, org.hibernate.SessionFactory) * * @param target The target object * @param sessionFactory The SessionFactory instance */ public static void setObjectToReadWrite(final Object target, SessionFactory sessionFactory) { Session session = sessionFactory.getCurrentSession(); if (!canModifyReadWriteState(session, target)) { return; } SessionImplementor sessionImpl = (SessionImplementor) session; EntityEntry ee = sessionImpl.getPersistenceContext().getEntry(target); if (ee == null || ee.getStatus() != Status.READ_ONLY) { return; } Object actualTarget = target; if (target instanceof HibernateProxy) { actualTarget = ((HibernateProxy)target).getHibernateLazyInitializer().getImplementation(); } session.setReadOnly(actualTarget, false); session.setFlushMode(FlushMode.AUTO); incrementVersion(target); }
private boolean updated(FlushEntityEvent event) { final EntityEntry entry = event.getEntityEntry(); final Object entity = event.getEntity(); int[] dirtyProperties; EntityPersister persister = entry.getPersister(); final Object[] values = event.getPropertyValues(); SessionImplementor session = event.getSession(); if ( event.hasDatabaseSnapshot() ) { dirtyProperties = persister.findModified( event.getDatabaseSnapshot(), values, entity, session ); } else { dirtyProperties = persister.findDirty( values, entry.getLoadedState(), entity, session ); } return dirtyProperties != null; }
/** * The entity instance is already in the session cache */ private void instanceAlreadyLoaded( final ResultSet rs, final int i, final Loadable persister, final EntityKey key, final Object object, final LockMode requestedLockMode, final SessionImplementor session) throws HibernateException, SQLException { if ( !persister.isInstance( object ) ) { throw new WrongClassException( "loaded object was of wrong class " + object.getClass(), key.getIdentifier(), persister.getEntityName() ); } if ( LockMode.NONE != requestedLockMode && upgradeLocks() ) { //no point doing this if NONE was requested final EntityEntry entry = session.getPersistenceContext().getEntry( object ); if ( entry.getLockMode().lessThan( requestedLockMode ) ) { //we only check the version when _upgrading_ lock modes if ( persister.isVersioned() ) { checkVersion( i, persister, key.getIdentifier(), object, rs, session ); } //we need to upgrade the lock mode to the mode requested entry.setLockMode( requestedLockMode ); } } }
public Object initializeLazyProperty(String fieldName, Object entity, SessionImplementor session) throws HibernateException { final Serializable id = session.getContextEntityIdentifier( entity ); final EntityEntry entry = session.getPersistenceContext().getEntry( entity ); if ( entry == null ) { throw new HibernateException( "entity is not associated with the session: " + id ); } if ( LOG.isTraceEnabled() ) { LOG.tracev( "Initializing lazy properties of: {0}, field access: {1}", MessageHelper.infoString( this, id, getFactory() ), fieldName ); } if ( session.getCacheMode().isGetEnabled() && hasCache() ) { final CacheKey cacheKey = session.generateCacheKey( id, getIdentifierType(), getEntityName() ); final Object ce = CacheHelper.fromSharedCache( session, cacheKey, getCacheAccessStrategy() ); if ( ce != null ) { final CacheEntry cacheEntry = (CacheEntry) getCacheEntryStructure().destructure(ce, factory); if ( !cacheEntry.areLazyPropertiesUnfetched() ) { //note early exit here: return initializeLazyPropertiesFromCache( fieldName, entity, session, entry, cacheEntry ); } } } return initializeLazyPropertiesFromDatastore( fieldName, entity, session, id, entry ); }
private Object initializeLazyPropertiesFromCache( final String fieldName, final Object entity, final SessionImplementor session, final EntityEntry entry, final CacheEntry cacheEntry ) { LOG.trace( "Initializing lazy properties from second-level cache" ); Object result = null; Serializable[] disassembledValues = cacheEntry.getDisassembledState(); final Object[] snapshot = entry.getLoadedState(); for ( int j = 0; j < lazyPropertyNames.length; j++ ) { final Object propValue = lazyPropertyTypes[j].assemble( disassembledValues[ lazyPropertyNumbers[j] ], session, entity ); if ( initializeLazyProperty( fieldName, entity, session, snapshot, j, propValue ) ) { result = propValue; } } LOG.trace( "Done initializing lazy properties" ); return result; }
/** * Delete an object */ public void delete(Serializable id, Object version, Object object, SessionImplementor session) throws HibernateException { final int span = getTableSpan(); boolean isImpliedOptimisticLocking = !entityMetamodel.isVersioned() && isAllOrDirtyOptLocking(); Object[] loadedState = null; if ( isImpliedOptimisticLocking ) { // need to treat this as if it where optimistic-lock="all" (dirty does *not* make sense); // first we need to locate the "loaded" state // // Note, it potentially could be a proxy, so doAfterTransactionCompletion the location the safe way... final EntityKey key = session.generateEntityKey( id, this ); Object entity = session.getPersistenceContext().getEntity( key ); if ( entity != null ) { EntityEntry entry = session.getPersistenceContext().getEntry( entity ); loadedState = entry.getLoadedState(); } } final String[] deleteStrings; if ( isImpliedOptimisticLocking && loadedState != null ) { // we need to utilize dynamic delete statements deleteStrings = generateSQLDeletStrings( loadedState ); } else { // otherwise, utilize the static delete statements deleteStrings = getSQLDeleteStrings(); } for ( int j = span - 1; j >= 0; j-- ) { delete( id, version, j, object, deleteStrings[j], session, loadedState ); } }
@Override public EntityEntry addEntity( final Object entity, final Status status, final Object[] loadedState, final EntityKey entityKey, final Object version, final LockMode lockMode, final boolean existsInDatabase, final EntityPersister persister, final boolean disableVersionIncrement, boolean lazyPropertiesAreUnfetched) { addEntity( entityKey, entity ); return addEntry( entity, status, loadedState, null, entityKey.getIdentifier(), version, lockMode, existsInDatabase, persister, disableVersionIncrement, lazyPropertiesAreUnfetched ); }
@Override public EntityEntry addEntry( final Object entity, final Status status, final Object[] loadedState, final Object rowId, final Serializable id, final Object version, final LockMode lockMode, final boolean existsInDatabase, final EntityPersister persister, final boolean disableVersionIncrement, boolean lazyPropertiesAreUnfetched) { final EntityEntry e = new EntityEntry( status, loadedState, rowId, id, version, lockMode, existsInDatabase, persister, disableVersionIncrement, lazyPropertiesAreUnfetched, this ); entityEntryContext.addEntityEntry( entity, e ); // entityEntries.put(entity, e); setHasNonReadOnlyEnties( status ); return e; }
@Override public Object proxyFor(Object impl) throws HibernateException { final EntityEntry e = getEntry( impl ); if ( e == null ) { return impl; } return proxyFor( e.getPersister(), e.getEntityKey(), impl ); }
private void setEntityReadOnly(Object entity, boolean readOnly) { final EntityEntry entry = getEntry( entity ); if ( entry == null ) { throw new TransientObjectException( "Instance was not associated with this persistence context" ); } entry.setReadOnly( readOnly, entity ); hasNonReadOnlyEntities = hasNonReadOnlyEntities || ! readOnly; }
private static boolean useMinimalPuts(SessionImplementor session, EntityEntry entityEntry) { return ( session.getFactory().getSettings().isMinimalPutsEnabled() && session.getCacheMode()!=CacheMode.REFRESH ) || ( entityEntry.getPersister().hasLazyProperties() && entityEntry.isLoadedWithLazyPropertiesUnfetched() && entityEntry.getPersister().isLazyPropertiesCacheable() ); }
/** * Get the id value for an object that is actually associated with the session. This * is a bit stricter than getEntityIdentifierIfNotUnsaved(). */ @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; } }
@Override public boolean contains(Object object) { errorIfClosed(); checkTransactionSynchStatus(); if ( object instanceof HibernateProxy ) { //do not use proxiesByKey, since not all //proxies that point to this session's //instances are in that collection! LazyInitializer li = ( (HibernateProxy) object ).getHibernateLazyInitializer(); if ( li.isUninitialized() ) { //if it is an uninitialized proxy, pointing //with this session, then when it is accessed, //the underlying instance will be "contained" return li.getSession()==this; } else { //if it is initialized, see if the underlying //instance is contained, since we need to //account for the fact that it might have been //evicted object = li.getImplementation(); } } // A session is considered to contain an entity only if the entity has // an entry in the session's persistence context and the entry reports // that the entity has not been removed EntityEntry entry = persistenceContext.getEntry( object ); delayedAfterCompletion(); return entry != null && entry.getStatus() != Status.DELETED && entry.getStatus() != Status.GONE; }
@Override public void lock(Serializable id, Object version, Object object, int timeout, SessionImplementor session) { if ( !lockable.isVersioned() ) { throw new OptimisticLockException( object, "[" + lockMode + "] not supported for non-versioned entities [" + lockable.getEntityName() + "]" ); } final EntityEntry entry = session.getPersistenceContext().getEntry( object ); // Register the EntityVerifyVersionProcess action to run just prior to transaction commit. ( (EventSource) session ).getActionQueue().registerProcess( new EntityVerifyVersionProcess( object, entry ) ); }
@Override public void lock(Serializable id, Object version, Object object, int timeout, SessionImplementor session) { if ( !lockable.isVersioned() ) { throw new HibernateException( "[" + lockMode + "] not supported for non-versioned entities [" + lockable.getEntityName() + "]" ); } final EntityEntry entry = session.getPersistenceContext().getEntry( object ); final EntityPersister persister = entry.getPersister(); final Object nextVersion = persister.forceVersionIncrement( entry.getId(), entry.getVersion(), session ); entry.forceLocked( object, nextVersion ); }
@Override public void lock(Serializable id, Object version, Object object, int timeout, SessionImplementor session) { if ( !lockable.isVersioned() ) { throw new HibernateException( "[" + lockMode + "] not supported for non-versioned entities [" + lockable.getEntityName() + "]" ); } final EntityEntry entry = session.getPersistenceContext().getEntry( object ); // Register the EntityIncrementVersionProcess action to run just prior to transaction commit. ( (EventSource) session ).getActionQueue().registerProcess( new EntityIncrementVersionProcess( object, entry ) ); }
protected static String getAffectedOwnerEntityName(CollectionPersister collectionPersister, Object affectedOwner, EventSource source ) { // collectionPersister should not be null, but we don't want to throw // an exception if it is null String entityName = ( collectionPersister == null ? null : collectionPersister.getOwnerEntityPersister().getEntityName() ); if ( affectedOwner != null ) { EntityEntry ee = source.getPersistenceContext().getEntry( affectedOwner ); if ( ee != null && ee.getEntityName() != null) { entityName = ee.getEntityName(); } } return entityName; }
protected Serializable performSaveOrUpdate(SaveOrUpdateEvent event) { // this implementation is supposed to tolerate incorrect unsaved-value // mappings, for the purpose of backward-compatibility EntityEntry entry = event.getSession().getPersistenceContext().getEntry( event.getEntity() ); if ( entry!=null && entry.getStatus() != Status.DELETED ) { return entityIsPersistent(event); } else { return entityIsTransient(event); } }
/** * Flushes a single entity's state to the database, by scheduling * an update action, if necessary */ public void onFlushEntity(FlushEntityEvent event) throws HibernateException { final Object entity = event.getEntity(); final EntityEntry entry = event.getEntityEntry(); final EventSource session = event.getSession(); final EntityPersister persister = entry.getPersister(); final Status status = entry.getStatus(); final Type[] types = persister.getPropertyTypes(); final boolean mightBeDirty = entry.requiresDirtyCheck( entity ); final Object[] values = getValues( entity, entry, mightBeDirty, session ); event.setPropertyValues( values ); //TODO: avoid this for non-new instances where mightBeDirty==false boolean substitute = wrapCollections( session, persister, types, values ); if ( isUpdateNecessary( event, mightBeDirty ) ) { substitute = scheduleUpdate( event ) || substitute; } if ( status != Status.DELETED ) { // now update the object .. has to be outside the main if block above (because of collections) if ( substitute ) { persister.setPropertyValues( entity, values ); } // Search for collections by reachability, updating their role. // We don't want to touch collections reachable from a deleted object if ( persister.hasCollections() ) { new FlushVisitor( session, entity ).processEntityPropertyValues( values, types ); } } }
protected boolean invokeInterceptor( SessionImplementor session, Object entity, EntityEntry entry, final Object[] values, EntityPersister persister) { return session.getInterceptor().onFlushDirty( entity, entry.getId(), values, entry.getLoadedState(), persister.getPropertyNames(), persister.getPropertyTypes() ); }
/** * Convience method to retreive an entities next version value */ private Object getNextVersion(FlushEntityEvent event) throws HibernateException { EntityEntry entry = event.getEntityEntry(); EntityPersister persister = entry.getPersister(); if ( persister.isVersioned() ) { Object[] values = event.getPropertyValues(); if ( entry.isBeingReplicated() ) { return Versioning.getVersion( values, persister ); } else { int[] dirtyProperties = event.getDirtyProperties(); final boolean isVersionIncrementRequired = isVersionIncrementRequired( event, entry, persister, dirtyProperties ); final Object nextVersion = isVersionIncrementRequired ? Versioning.increment( entry.getVersion(), persister.getVersionType(), event.getSession() ) : entry.getVersion(); //use the current version Versioning.setVersion( values, nextVersion, persister ); return nextVersion; } } else { return null; } }
/** * If there is already a corresponding proxy associated with the * persistence context, return it; otherwise create a proxy, associate it * with the persistence context, and return the just-created proxy. * * @param event The initiating load request event * @param persister The persister corresponding to the entity to be loaded * @param keyToLoad The key of the entity to be loaded * @param options The defined load options * @param persistenceContext The originating session * * @return The created/existing proxy */ private Object createProxyIfNecessary( final LoadEvent event, final EntityPersister persister, final EntityKey keyToLoad, final LoadEventListener.LoadType options, final PersistenceContext persistenceContext) { Object existing = persistenceContext.getEntity( keyToLoad ); if ( existing != null ) { // return existing object or initialized proxy (unless deleted) LOG.trace( "Entity found in session cache" ); if ( options.isCheckDeleted() ) { EntityEntry entry = persistenceContext.getEntry( existing ); Status status = entry.getStatus(); if ( status == Status.DELETED || status == Status.GONE ) { return null; } } return existing; } LOG.trace( "Creating new proxy for entity" ); // return new uninitialized proxy Object proxy = persister.createProxy( event.getEntityId(), event.getSession() ); persistenceContext.getBatchFetchQueue().addBatchLoadableEntityKey( keyToLoad ); persistenceContext.addProxy( keyToLoad, proxy ); return proxy; }
/** * Attempts to locate the entity in the session-level cache. * <p/> * If allowed to return nulls, then if the entity happens to be found in * the session cache, we check the entity type for proper handling * of entity hierarchies. * <p/> * If checkDeleted was set to true, then if the entity is found in the * session-level cache, it's current status within the session cache * is checked to see if it has previously been scheduled for deletion. * * @param event The load event * @param keyToLoad The EntityKey representing the entity to be loaded. * @param options The load options. * * @return The entity from the session-level cache, or null. * * @throws HibernateException Generally indicates problems applying a lock-mode. */ protected Object loadFromSessionCache( final LoadEvent event, final EntityKey keyToLoad, final LoadEventListener.LoadType options) throws HibernateException { SessionImplementor session = event.getSession(); Object old = session.getEntityUsingInterceptor( keyToLoad ); if ( old != null ) { // this object was already loaded EntityEntry oldEntry = session.getPersistenceContext().getEntry( old ); if ( options.isCheckDeleted() ) { Status status = oldEntry.getStatus(); if ( status == Status.DELETED || status == Status.GONE ) { return REMOVED_ENTITY_MARKER; } } if ( options.isAllowNulls() ) { final EntityPersister persister = event.getSession() .getFactory() .getEntityPersister( keyToLoad.getEntityName() ); if ( !persister.isInstance( old ) ) { return INCONSISTENT_RTN_CLASS_MARKER; } } upgradeLock( old, oldEntry, event.getLockOptions(), event.getSession() ); } return old; }
/** * Handle the given lock event. * * @param event The lock event to be handled. * @throws HibernateException */ public void onLock(LockEvent event) throws HibernateException { if ( event.getObject() == null ) { throw new NullPointerException( "attempted to lock null" ); } if ( event.getLockMode() == LockMode.WRITE ) { throw new HibernateException( "Invalid lock mode for lock()" ); } if ( event.getLockMode() == LockMode.UPGRADE_SKIPLOCKED ) { LOG.explicitSkipLockedLockCombo(); } SessionImplementor source = event.getSession(); Object entity = source.getPersistenceContext().unproxyAndReassociate( event.getObject() ); //TODO: if object was an uninitialized proxy, this is inefficient, // resulting in two SQL selects EntityEntry entry = source.getPersistenceContext().getEntry(entity); if (entry==null) { final EntityPersister persister = source.getEntityPersister( event.getEntityName(), entity ); final Serializable id = persister.getIdentifier( entity, source ); if ( !ForeignKeys.isNotTransient( event.getEntityName(), entity, Boolean.FALSE, source ) ) { throw new TransientObjectException( "cannot lock an unsaved transient instance: " + persister.getEntityName() ); } entry = reassociate(event, entity, id, persister); cascadeOnLock(event, persister, entity); } upgradeLock( entity, entry, event.getLockOptions(), event.getSession() ); }