FileDocCategorySizeDatePackage
StatefulPersistenceContext.javaAPI DocHibernate 3.2.543814Thu Jun 07 13:22:50 BST 2007org.hibernate.engine

StatefulPersistenceContext

public class StatefulPersistenceContext extends Object implements PersistenceContext
A PersistenceContext represents the state of persistent "stuff" which Hibernate is tracking. This includes persistent entities, collections, as well as proxies generated.

There is meant to be a one-to-one correspondence between a SessionImpl and a PersistentContext. The SessionImpl uses the PersistentContext to track the current state of its context. Event-listeners then use the PersistentContext to drive their processing.
author
Steve Ebersole

Fields Summary
public static final Object
NO_ROW
private static final Log
log
private static final Log
PROXY_WARN_LOG
private static final int
INIT_COLL_SIZE
private SessionImplementor
session
private Map
entitiesByKey
private Map
entitiesByUniqueKey
private Map
entityEntries
private Map
proxiesByKey
private Map
entitySnapshotsByKey
private Map
arrayHolders
private Map
collectionEntries
private Map
collectionsByKey
private HashSet
nullifiableEntityKeys
private HashSet
nullAssociations
private List
nonlazyCollections
private Map
unownedCollections
private int
cascading
private int
loadCounter
private boolean
flushing
private boolean
hasNonReadOnlyEntities
private org.hibernate.engine.loading.LoadContexts
loadContexts
private BatchFetchQueue
batchFetchQueue
Constructors Summary
public StatefulPersistenceContext(SessionImplementor session)
Constructs a PersistentContext, bound to the given session.

param
session The session "owning" this context.




	               	 
	   
		this.session = session;

		entitiesByKey = new HashMap( INIT_COLL_SIZE );
		entitiesByUniqueKey = new HashMap( INIT_COLL_SIZE );
		proxiesByKey = new ReferenceMap( ReferenceMap.HARD, ReferenceMap.WEAK );
		entitySnapshotsByKey = new HashMap( INIT_COLL_SIZE );

		entityEntries = IdentityMap.instantiateSequenced( INIT_COLL_SIZE );
		collectionEntries = IdentityMap.instantiateSequenced( INIT_COLL_SIZE );
		collectionsByKey = new HashMap( INIT_COLL_SIZE );
		arrayHolders = IdentityMap.instantiate( INIT_COLL_SIZE );

		nullifiableEntityKeys = new HashSet();

		initTransientState();
	
Methods Summary
private voidaddCollection(org.hibernate.collection.PersistentCollection coll, CollectionEntry entry, java.io.Serializable key)
Add an collection to the cache, with a given collection entry.

param
coll The collection for which we are adding an entry.
param
entry The entry representing the collection.
param
key The key of the collection's entry.

		collectionEntries.put( coll, entry );
		CollectionKey collectionKey = new CollectionKey( entry.getLoadedPersister(), key, session.getEntityMode() );
		PersistentCollection old = ( PersistentCollection ) collectionsByKey.put( collectionKey, coll );
		if ( old != null ) {
			if ( old == coll ) {
				throw new AssertionFailure("bug adding collection twice");
			}
			// or should it actually throw an exception?
			old.unsetSession( session );
			collectionEntries.remove( old );
			// watch out for a case where old is still referenced
			// somewhere in the object graph! (which is a user error)
		}
	
private voidaddCollection(org.hibernate.collection.PersistentCollection collection, org.hibernate.persister.collection.CollectionPersister persister)
Add a collection to the cache, creating a new collection entry for it

param
collection The collection for which we are adding an entry.
param
persister The collection persister

		CollectionEntry ce = new CollectionEntry( persister, collection );
		collectionEntries.put( collection, ce );
	
public voidaddCollectionHolder(org.hibernate.collection.PersistentCollection holder)
Register a PersistentCollection object for an array. Associates a holder with an array - MUST be called after loading array, since the array instance is not created until endLoad().

		//TODO:refactor + make this method private
		arrayHolders.put( holder.getValue(), holder );
	
public voidaddEntity(EntityKey key, java.lang.Object entity)

		entitiesByKey.put(key, entity);
		getBatchFetchQueue().removeBatchLoadableEntityKey(key);
	
public voidaddEntity(EntityUniqueKey euk, java.lang.Object entity)
Add an entity to the cache by unique key

		entitiesByUniqueKey.put(euk, entity);
	
public EntityEntryaddEntity(java.lang.Object entity, Status status, java.lang.Object[] loadedState, EntityKey entityKey, java.lang.Object version, org.hibernate.LockMode lockMode, boolean existsInDatabase, org.hibernate.persister.entity.EntityPersister persister, boolean disableVersionIncrement, boolean lazyPropertiesAreUnfetched)
Adds an entity to the internal caches.

		
		addEntity( entityKey, entity );
		
		return addEntry(
				entity,
				status,
				loadedState,
				null,
				entityKey.getIdentifier(),
				version,
				lockMode,
				existsInDatabase,
				persister,
				disableVersionIncrement, 
				lazyPropertiesAreUnfetched
			);
	
public EntityEntryaddEntry(java.lang.Object entity, Status status, java.lang.Object[] loadedState, java.lang.Object rowId, java.io.Serializable id, java.lang.Object version, org.hibernate.LockMode lockMode, boolean existsInDatabase, org.hibernate.persister.entity.EntityPersister persister, boolean disableVersionIncrement, boolean lazyPropertiesAreUnfetched)
Generates an appropriate EntityEntry instance and adds it to the event source's internal caches.

		
		EntityEntry e = new EntityEntry(
				status,
				loadedState,
				rowId,
				id,
				version,
				lockMode,
				existsInDatabase,
				persister,
				session.getEntityMode(),
				disableVersionIncrement,
				lazyPropertiesAreUnfetched
			);
		entityEntries.put(entity, e);
		
		setHasNonReadOnlyEnties(status);
		return e;
	
public CollectionEntryaddInitializedCollection(org.hibernate.persister.collection.CollectionPersister persister, org.hibernate.collection.PersistentCollection collection, java.io.Serializable id)
add a collection we just pulled out of the cache (does not need initializing)

		CollectionEntry ce = new CollectionEntry(collection, persister, id, flushing);
		ce.postInitialize(collection);
		addCollection(collection, ce, id);
		return ce;
	
public voidaddInitializedDetachedCollection(org.hibernate.persister.collection.CollectionPersister collectionPersister, org.hibernate.collection.PersistentCollection collection)
add an (initialized) collection that was created by another session and passed into update() (ie. one with a snapshot and existing state on the database)

		if ( collection.isUnreferenced() ) {
			//treat it just like a new collection
			addCollection( collection, collectionPersister );
		}
		else {
			CollectionEntry ce = new CollectionEntry( collection, session.getFactory() );
			addCollection( collection, ce, collection.getKey() );
		}
	
public voidaddNewCollection(org.hibernate.persister.collection.CollectionPersister persister, org.hibernate.collection.PersistentCollection collection)
Add a new collection (ie. a newly created one, just instantiated by the application, with no database state or snapshot)

param
collection The collection to be associated with the persistence context

		addCollection(collection, persister);
	
public voidaddNonLazyCollection(org.hibernate.collection.PersistentCollection collection)
Register a collection for non-lazy loading at the end of the two-phase load

		nonlazyCollections.add(collection);
	
public voidaddNullProperty(EntityKey ownerKey, java.lang.String propertyName)
Record the fact that the association belonging to the keyed entity is null.

		nullAssociations.add( new AssociationKey(ownerKey, propertyName) );
	
public voidaddProxy(EntityKey key, java.lang.Object proxy)
Add a proxy to the session cache

		proxiesByKey.put(key, proxy);
	
public voidaddUninitializedCollection(org.hibernate.persister.collection.CollectionPersister persister, org.hibernate.collection.PersistentCollection collection, java.io.Serializable id)
add a collection we just loaded up (still needs initializing)

		CollectionEntry ce = new CollectionEntry(collection, persister, id, flushing);
		addCollection(collection, ce, id);
	
public voidaddUninitializedDetachedCollection(org.hibernate.persister.collection.CollectionPersister persister, org.hibernate.collection.PersistentCollection collection)
add a detached uninitialized collection

		CollectionEntry ce = new CollectionEntry( persister, collection.getKey() );
		addCollection( collection, ce, collection.getKey() );
	
public voidaddUnownedCollection(CollectionKey key, org.hibernate.collection.PersistentCollection collection)

		if (unownedCollections==null) {
			unownedCollections = new HashMap(8);
		}
		unownedCollections.put(key, collection);
	
public voidafterLoad()
Call this after finishing a two-phase load

		loadCounter--;
	
public voidafterTransactionCompletion()

		// Downgrade locks
		Iterator iter = entityEntries.values().iterator();
		while ( iter.hasNext() ) {
			( (EntityEntry) iter.next() ).setLockMode(LockMode.NONE);
		}
	
public voidbeforeLoad()
Call this before begining a two-phase load

		loadCounter++;
	
public voidcheckUniqueness(EntityKey key, java.lang.Object object)
Attempts to check whether the given key represents an entity already loaded within the current session.

param
object The entity reference against which to perform the uniqueness check.
throws
HibernateException

		Object entity = getEntity(key);
		if ( entity == object ) {
			throw new AssertionFailure( "object already associated, but no entry was found" );
		}
		if ( entity != null ) {
			throw new NonUniqueObjectException( key.getIdentifier(), key.getEntityName() );
		}
	
public voidclear()

		Iterator itr = proxiesByKey.values().iterator();
		while ( itr.hasNext() ) {
			final LazyInitializer li = ( ( HibernateProxy ) itr.next() ).getHibernateLazyInitializer();
			li.setSession( null );
		}
		Map.Entry[] collectionEntryArray = IdentityMap.concurrentEntries( collectionEntries );
		for ( int i = 0; i < collectionEntryArray.length; i++ ) {
			( ( PersistentCollection ) collectionEntryArray[i].getKey() ).unsetSession( getSession() );
		}
		arrayHolders.clear();
		entitiesByKey.clear();
		entitiesByUniqueKey.clear();
		entityEntries.clear();
		entitySnapshotsByKey.clear();
		collectionsByKey.clear();
		collectionEntries.clear();
		if ( unownedCollections != null ) {
			unownedCollections.clear();
		}
		proxiesByKey.clear();
		nullifiableEntityKeys.clear();
		if ( batchFetchQueue != null ) {
			batchFetchQueue.clear();
		}
		hasNonReadOnlyEntities = false;
		if ( loadContexts != null ) {
			loadContexts.cleanup();
		}
	
private voidclearNullProperties()

		nullAssociations.clear();
	
public booleancontainsCollection(org.hibernate.collection.PersistentCollection collection)

		return collectionEntries.containsKey(collection);
	
public booleancontainsEntity(EntityKey key)

		return entitiesByKey.containsKey(key);
	
public booleancontainsProxy(java.lang.Object entity)

		return proxiesByKey.containsValue( entity );
	
public intdecrementCascadeLevel()

		return --cascading;
	
public static org.hibernate.engine.StatefulPersistenceContextdeserialize(java.io.ObjectInputStream ois, SessionImplementor session)

		log.trace( "deserializing persistent-context" );
		StatefulPersistenceContext rtn = new StatefulPersistenceContext( session );

		// during deserialization, we need to reconnect all proxies and
		// collections to this session, as well as the EntityEntry and
		// CollectionEntry instances; these associations are transient
		// because serialization is used for different things.

		try {
			// todo : we can actually just determine this from the incoming EntityEntry-s
			rtn.hasNonReadOnlyEntities = ois.readBoolean();

			int count = ois.readInt();
			log.trace( "staring deserialization of [" + count + "] entitiesByKey entries" );
			rtn.entitiesByKey = new HashMap( count < INIT_COLL_SIZE ? INIT_COLL_SIZE : count );
			for ( int i = 0; i < count; i++ ) {
				rtn.entitiesByKey.put( EntityKey.deserialize( ois, session ), ois.readObject() );
			}

			count = ois.readInt();
			log.trace( "staring deserialization of [" + count + "] entitiesByUniqueKey entries" );
			rtn.entitiesByUniqueKey = new HashMap( count < INIT_COLL_SIZE ? INIT_COLL_SIZE : count );
			for ( int i = 0; i < count; i++ ) {
				rtn.entitiesByUniqueKey.put( EntityUniqueKey.deserialize( ois, session ), ois.readObject() );
			}

			count = ois.readInt();
			log.trace( "staring deserialization of [" + count + "] proxiesByKey entries" );
			rtn.proxiesByKey = new ReferenceMap( ReferenceMap.HARD, ReferenceMap.WEAK, count < INIT_COLL_SIZE ? INIT_COLL_SIZE : count, .75f );
			for ( int i = 0; i < count; i++ ) {
				EntityKey ek = EntityKey.deserialize( ois, session );
				Object proxy = ois.readObject();
				if ( proxy instanceof HibernateProxy ) {
					( ( HibernateProxy ) proxy ).getHibernateLazyInitializer().setSession( session );
					rtn.proxiesByKey.put( ek, proxy );
				}
				else {
					log.trace( "encountered prunded proxy" );
				}
				// otherwise, the proxy was pruned during the serialization process
			}

			count = ois.readInt();
			log.trace( "staring deserialization of [" + count + "] entitySnapshotsByKey entries" );
			rtn.entitySnapshotsByKey = new HashMap( count < INIT_COLL_SIZE ? INIT_COLL_SIZE : count );
			for ( int i = 0; i < count; i++ ) {
				rtn.entitySnapshotsByKey.put( EntityKey.deserialize( ois, session ), ois.readObject() );
			}

			count = ois.readInt();
			log.trace( "staring deserialization of [" + count + "] entityEntries entries" );
			rtn.entityEntries = IdentityMap.instantiateSequenced( count < INIT_COLL_SIZE ? INIT_COLL_SIZE : count );
			for ( int i = 0; i < count; i++ ) {
				Object entity = ois.readObject();
				EntityEntry entry = EntityEntry.deserialize( ois, session );
				rtn.entityEntries.put( entity, entry );
			}

			count = ois.readInt();
			log.trace( "staring deserialization of [" + count + "] collectionsByKey entries" );
			rtn.collectionsByKey = new HashMap( count < INIT_COLL_SIZE ? INIT_COLL_SIZE : count );
			for ( int i = 0; i < count; i++ ) {
				rtn.collectionsByKey.put( CollectionKey.deserialize( ois, session ), ois.readObject() );
			}

			count = ois.readInt();
			log.trace( "staring deserialization of [" + count + "] collectionEntries entries" );
			rtn.collectionEntries = IdentityMap.instantiateSequenced( count < INIT_COLL_SIZE ? INIT_COLL_SIZE : count );
			for ( int i = 0; i < count; i++ ) {
				final PersistentCollection pc = ( PersistentCollection ) ois.readObject();
				final CollectionEntry ce = CollectionEntry.deserialize( ois, session );
				pc.setCurrentSession( session );
				rtn.collectionEntries.put( pc, ce );
			}

			count = ois.readInt();
			log.trace( "staring deserialization of [" + count + "] arrayHolders entries" );
			rtn.arrayHolders = IdentityMap.instantiate( count < INIT_COLL_SIZE ? INIT_COLL_SIZE : count );
			for ( int i = 0; i < count; i++ ) {
				rtn.arrayHolders.put( ois.readObject(), ois.readObject() );
			}

			count = ois.readInt();
			log.trace( "staring deserialization of [" + count + "] nullifiableEntityKeys entries" );
			rtn.nullifiableEntityKeys = new HashSet();
			for ( int i = 0; i < count; i++ ) {
				rtn.nullifiableEntityKeys.add( EntityKey.deserialize( ois, session ) );
			}

		}
		catch ( HibernateException he ) {
			throw new InvalidObjectException( he.getMessage() );
		}

		return rtn;
	
public BatchFetchQueuegetBatchFetchQueue()
Get the BatchFetchQueue, instantiating one if necessary.

		if (batchFetchQueue==null) {
			batchFetchQueue = new BatchFetchQueue(this);
		}
		return batchFetchQueue;
	
public java.lang.Object[]getCachedDatabaseSnapshot(EntityKey key)
Retrieve the cached database snapshot for the requested entity key.

This differs from {@link #getDatabaseSnapshot} is two important respects:

  1. no snapshot is obtained from the database if not already cached
  2. an entry of {@link #NO_ROW} here is interpretet as an exception

param
key The entity key for which to retrieve the cached snapshot
return
The cached snapshot
throws
IllegalStateException if the cached snapshot was == {@link #NO_ROW}.

		Object snapshot = entitySnapshotsByKey.get( key );
		if ( snapshot == NO_ROW ) {
			throw new IllegalStateException( "persistence context reported no row snapshot for " + MessageHelper.infoString( key.getEntityName(), key.getIdentifier() ) );
		}
		return ( Object[] ) snapshot;
	
public intgetCascadeLevel()
Do we already know that the entity does not exist in the database?

		return cascading;
	
public org.hibernate.collection.PersistentCollectiongetCollection(CollectionKey collectionKey)
Get the collection instance associated with the CollectionKey

		return (PersistentCollection) collectionsByKey.get(collectionKey);
	
public java.util.MapgetCollectionEntries()

		return collectionEntries;
	
public CollectionEntrygetCollectionEntry(org.hibernate.collection.PersistentCollection coll)
Get the collection entry for a persistent collection

		return (CollectionEntry) collectionEntries.get(coll);
	
public CollectionEntrygetCollectionEntryOrNull(java.lang.Object collection)
Get the collection entry for a collection passed to filter, which might be a collection wrapper, an array, or an unwrapped collection. Return null if there is no entry.

		PersistentCollection coll;
		if ( collection instanceof PersistentCollection ) {
			coll = (PersistentCollection) collection;
			//if (collection==null) throw new TransientObjectException("Collection was not yet persistent");
		}
		else {
			coll = getCollectionHolder(collection);
			if ( coll == null ) {
				//it might be an unwrapped collection reference!
				//try to find a wrapper (slowish)
				Iterator wrappers = IdentityMap.keyIterator(collectionEntries);
				while ( wrappers.hasNext() ) {
					PersistentCollection pc = (PersistentCollection) wrappers.next();
					if ( pc.isWrapper(collection) ) {
						coll = pc;
						break;
					}
				}
			}
		}

		return (coll == null) ? null : getCollectionEntry(coll);
	
public org.hibernate.collection.PersistentCollectiongetCollectionHolder(java.lang.Object array)
Get the PersistentCollection object for an array

		return (PersistentCollection) arrayHolders.get(array);
	
public java.lang.ObjectgetCollectionOwner(java.io.Serializable key, org.hibernate.persister.collection.CollectionPersister collectionPersister)
Get the entity that owns this persistent collection

		return getEntity( new EntityKey( key, collectionPersister.getOwnerEntityPersister(), session.getEntityMode() ) );
	
public java.util.MapgetCollectionsByKey()

		return collectionsByKey;
	
public java.lang.Object[]getDatabaseSnapshot(java.io.Serializable id, org.hibernate.persister.entity.EntityPersister persister)
Get the current state of the entity as known to the underlying database, or null if there is no corresponding row

		EntityKey key = new EntityKey( id, persister, session.getEntityMode() );
		Object cached = entitySnapshotsByKey.get(key);
		if (cached!=null) {
			return cached==NO_ROW ? null : (Object[]) cached;
		}
		else {
			Object[] snapshot = persister.getDatabaseSnapshot( id, session );
			entitySnapshotsByKey.put( key, snapshot==null ? NO_ROW : snapshot );
			return snapshot;
		}
	
public java.util.MapgetEntitiesByKey()

		return entitiesByKey;
	
public java.lang.ObjectgetEntity(EntityKey key)
Get the entity instance associated with the given EntityKey

		return entitiesByKey.get(key);
	
public java.lang.ObjectgetEntity(EntityUniqueKey euk)
Get an entity cached by unique key

		return entitiesByUniqueKey.get(euk);
	
public java.util.MapgetEntityEntries()

		return entityEntries;
	
public EntityEntrygetEntry(java.lang.Object entity)
Retreive the EntityEntry representation of the given entity.

param
entity The entity for which to locate the EntityEntry.
return
The EntityEntry for the given entity.

		return (EntityEntry) entityEntries.get(entity);
	
public java.lang.ObjectgetIndexInOwner(java.lang.String entity, java.lang.String property, java.lang.Object childEntity, java.util.Map mergeMap)
Search the persistence context for an index of the child object, given a collection role


		EntityPersister persister = session.getFactory()
				.getEntityPersister(entity);
		CollectionPersister cp = session.getFactory()
				.getCollectionPersister(entity + '." + property);
		Iterator entities = entityEntries.entrySet().iterator();
		while ( entities.hasNext() ) {
			Map.Entry me = (Map.Entry) entities.next();
			EntityEntry ee = (EntityEntry) me.getValue();
			if ( persister.isSubclassEntityName( ee.getEntityName() ) ) {
				Object instance = me.getKey();
				
				Object index = getIndexInParent(property, childEntity, persister, cp, instance);
				
				if (index==null && mergeMap!=null) {
					Object unmergedInstance = mergeMap.get(instance);
					Object unmergedChild = mergeMap.get(childEntity);
					if ( unmergedInstance!=null && unmergedChild!=null ) {
						index = getIndexInParent(property, unmergedChild, persister, cp, unmergedInstance);
					}
				}
				
				if (index!=null) return index;
			}
		}
		return null;
	
private java.lang.ObjectgetIndexInParent(java.lang.String property, java.lang.Object childEntity, org.hibernate.persister.entity.EntityPersister persister, org.hibernate.persister.collection.CollectionPersister collectionPersister, java.lang.Object potentialParent)

	
		Object collection = persister.getPropertyValue( potentialParent, property, session.getEntityMode() );
		if ( collection!=null && Hibernate.isInitialized(collection) ) {
			return collectionPersister.getCollectionType().indexOf(collection, childEntity);
		}
		else {
			return null;
		}
	
public org.hibernate.engine.loading.LoadContextsgetLoadContexts()

		if ( loadContexts == null ) {
			loadContexts = new LoadContexts( this );
		}
		return loadContexts;
	
public java.lang.Object[]getNaturalIdSnapshot(java.io.Serializable id, org.hibernate.persister.entity.EntityPersister persister)

		if ( !persister.hasNaturalIdentifier() ) {
			return null;
		}

		// if the natural-id is marked as non-mutable, it is not retrieved during a
		// normal database-snapshot operation...
		int[] props = persister.getNaturalIdentifierProperties();
		boolean[] updateable = persister.getPropertyUpdateability();
		boolean allNatualIdPropsAreUpdateable = true;
		for ( int i = 0; i < props.length; i++ ) {
			if ( !updateable[ props[i] ] ) {
				allNatualIdPropsAreUpdateable = false;
				break;
			}
		}

		if ( allNatualIdPropsAreUpdateable ) {
			// do this when all the properties are updateable since there is
			// a certain likelihood that the information will already be
			// snapshot-cached.
			Object[] entitySnapshot = getDatabaseSnapshot( id, persister );
			if ( entitySnapshot == NO_ROW ) {
				return null;
			}
			Object[] naturalIdSnapshot = new Object[ props.length ];
			for ( int i = 0; i < props.length; i++ ) {
				naturalIdSnapshot[i] = entitySnapshot[ props[i] ];
			}
			return naturalIdSnapshot;
		}
		else {
			return persister.getNaturalIdentifierSnapshot( id, session );
		}
	
public java.util.HashSetgetNullifiableEntityKeys()
Retrieve the set of EntityKeys representing nullifiable references

		return nullifiableEntityKeys;
	
public java.io.SerializablegetOwnerId(java.lang.String entity, java.lang.String property, java.lang.Object childEntity, java.util.Map mergeMap)
Search the persistence context for an owner for the child object, given a collection role. If mergeMap is non-null, also check the detached graph being merged for a parent.

		
		EntityPersister persister = session.getFactory()
				.getEntityPersister(entity);
		final CollectionPersister collectionPersister = session.getFactory()
				.getCollectionPersister(entity + '." + property);
		
		Iterator entities = entityEntries.entrySet().iterator();
		while ( entities.hasNext() ) {
			Map.Entry me = (Map.Entry) entities.next();
			EntityEntry ee = (EntityEntry) me.getValue();
			if ( persister.isSubclassEntityName( ee.getEntityName() ) ) {
				Object instance = me.getKey();

				//check if the managed object is the parent
				boolean found = isFoundInParent( 
						property, 
						childEntity, 
						persister, 
						collectionPersister,
						instance 
					);

				if (!found && mergeMap!=null) {
					//check if the detached object being merged is the parent
					Object unmergedInstance = mergeMap.get(instance);
					Object unmergedChild = mergeMap.get(childEntity);
					if ( unmergedInstance!=null && unmergedChild!=null ) {
						found = isFoundInParent( 
								property, 
								unmergedChild, 
								persister, 
								collectionPersister,
								unmergedInstance 
							);
					}
				}
				
				if ( found ) {
					return ee.getId();
				}
				
			}
		}
		return null;
	
public java.lang.ObjectgetProxy(EntityKey key)
Get an existing proxy by key

		return proxiesByKey.get(key);
	
public SessionImplementorgetSession()

		return session;
	
public java.io.SerializablegetSnapshot(org.hibernate.collection.PersistentCollection coll)
Get the snapshot of the pre-flush collection state

		return getCollectionEntry(coll).getSnapshot();
	
public booleanhasNonReadOnlyEntities()

		return hasNonReadOnlyEntities;
	
public intincrementCascadeLevel()

		return ++cascading;
	
private voidinitTransientState()

		nullAssociations = new HashSet( INIT_COLL_SIZE );
		nonlazyCollections = new ArrayList( INIT_COLL_SIZE );
	
public voidinitializeNonLazyCollections()
Force initialization of all non-lazy collections encountered during the current two-phase load (actually, this is a no-op, unless this is the "outermost" load)

		if ( loadCounter == 0 ) {
			log.debug( "initializing non-lazy collections" );
			//do this work only at the very highest level of the load
			loadCounter++; //don't let this method be called recursively
			try {
				int size;
				while ( ( size = nonlazyCollections.size() ) > 0 ) {
					//note that each iteration of the loop may add new elements
					( (PersistentCollection) nonlazyCollections.remove( size - 1 ) ).forceInitialization();
				}
			}
			finally {
				loadCounter--;
				clearNullProperties();
			}
		}
	
public booleanisEntryFor(java.lang.Object entity)
Is there an EntityEntry for this instance?

		return entityEntries.containsKey(entity);
	
public booleanisFlushing()

		return flushing;
	
private booleanisFoundInParent(java.lang.String property, java.lang.Object childEntity, org.hibernate.persister.entity.EntityPersister persister, org.hibernate.persister.collection.CollectionPersister collectionPersister, java.lang.Object potentialParent)

		Object collection = persister.getPropertyValue( 
				potentialParent, 
				property, 
				session.getEntityMode() 
			);
		return collection!=null && Hibernate.isInitialized(collection) &&
				collectionPersister.getCollectionType()
						.contains(collection, childEntity, session);
	
public booleanisPropertyNull(EntityKey ownerKey, java.lang.String propertyName)
Is the association property belonging to the keyed entity null?

		return nullAssociations.contains( new AssociationKey(ownerKey, propertyName) );
	
public booleanisStateless()

		return false;
	
public java.lang.ObjectnarrowProxy(java.lang.Object proxy, org.hibernate.persister.entity.EntityPersister persister, EntityKey key, java.lang.Object object)
If the existing proxy is insufficiently "narrow" (derived), instantiate a new proxy and overwrite the registration of the old one. This breaks == and occurs only for "class" proxies rather than "interface" proxies. Also init the proxy to point to the given target implementation if necessary.

param
proxy The proxy instance to be narrowed.
param
persister The persister for the proxied entity.
param
key The internal cache key for the proxied entity.
param
object (optional) the actual proxied entity instance.
return
An appropriately narrowed instance.
throws
HibernateException

		
		boolean alreadyNarrow = persister.getConcreteProxyClass( session.getEntityMode() )
				.isAssignableFrom( proxy.getClass() );
		
		if ( !alreadyNarrow ) {
			if ( PROXY_WARN_LOG.isWarnEnabled() ) {
				PROXY_WARN_LOG.warn(
						"Narrowing proxy to " +
						persister.getConcreteProxyClass( session.getEntityMode() ) +
						" - this operation breaks =="
				);
			}

			if ( object != null ) {
				proxiesByKey.remove(key);
				return object; //return the proxied object
			}
			else {
				proxy = persister.createProxy( key.getIdentifier(), session );
				proxiesByKey.put(key, proxy); //overwrite old proxy
				return proxy;
			}
			
		}
		else {
			
			if ( object != null ) {
				LazyInitializer li = ( (HibernateProxy) proxy ).getHibernateLazyInitializer();
				li.setImplementation(object);
			}
			
			return proxy;
			
		}
		
	
public java.lang.ObjectproxyFor(org.hibernate.persister.entity.EntityPersister persister, EntityKey key, java.lang.Object impl)
Return the existing proxy associated with the given EntityKey, or the third argument (the entity associated with the key) if no proxy exists. Init the proxy to the target implementation, if necessary.

		if ( !persister.hasProxy() ) return impl;
		Object proxy = proxiesByKey.get(key);
		if ( proxy != null ) {
			return narrowProxy(proxy, persister, key, impl);
		}
		else {
			return impl;
		}
	
public java.lang.ObjectproxyFor(java.lang.Object impl)
Return the existing proxy associated with the given EntityKey, or the argument (the entity associated with the key) if no proxy exists. (slower than the form above)

		EntityEntry e = getEntry(impl);
		EntityPersister p = e.getPersister();
		return proxyFor( p, new EntityKey( e.getId(), p, session.getEntityMode() ), impl );
	
public booleanreassociateIfUninitializedProxy(java.lang.Object value)
Takes the given object and, if it represents a proxy, reassociates it with this event source.

param
value The possible proxy to be reassociated.
return
Whether the passed value represented an actual proxy which got initialized.
throws
MappingException

		if ( value instanceof ElementWrapper ) {
			value = ( (ElementWrapper) value ).getElement();
		}
		
		if ( !Hibernate.isInitialized(value) ) {
			HibernateProxy proxy = (HibernateProxy) value;
			LazyInitializer li = proxy.getHibernateLazyInitializer();
			reassociateProxy(li, proxy);
			return true;
		}
		else {
			return false;
		}
	
public voidreassociateProxy(java.lang.Object value, java.io.Serializable id)
If a deleted entity instance is re-saved, and it has a proxy, we need to reset the identifier of the proxy

		if ( value instanceof ElementWrapper ) {
			value = ( (ElementWrapper) value ).getElement();
		}
		
		if ( value instanceof HibernateProxy ) {
			if ( log.isDebugEnabled() ) log.debug("setting proxy identifier: " + id);
			HibernateProxy proxy = (HibernateProxy) value;
			LazyInitializer li = proxy.getHibernateLazyInitializer();
			li.setIdentifier(id);
			reassociateProxy(li, proxy);
		}
	
private voidreassociateProxy(org.hibernate.proxy.LazyInitializer li, org.hibernate.proxy.HibernateProxy proxy)
Associate a proxy that was instantiated by another session with this session

param
li The proxy initializer.
param
proxy The proxy to reassociate.

		if ( li.getSession() != this.getSession() ) {
			EntityPersister persister = session.getFactory().getEntityPersister( li.getEntityName() );
			EntityKey key = new EntityKey( li.getIdentifier(), persister, session.getEntityMode() );
		  	// any earlier proxy takes precedence
			if ( !proxiesByKey.containsKey( key ) ) {
				proxiesByKey.put( key, proxy );
			}
			proxy.getHibernateLazyInitializer().setSession( session );
		}
	
public org.hibernate.collection.PersistentCollectionremoveCollectionHolder(java.lang.Object array)

		return (PersistentCollection) arrayHolders.remove(array);
	
public java.lang.ObjectremoveEntity(EntityKey key)
Remove an entity from the session cache, also clear up other state associated with the entity, all except for the EntityEntry

		Object entity = entitiesByKey.remove(key);
		Iterator iter = entitiesByUniqueKey.values().iterator();
		while ( iter.hasNext() ) {
			if ( iter.next()==entity ) iter.remove();
		}
		entitySnapshotsByKey.remove(key);
		nullifiableEntityKeys.remove(key);
		getBatchFetchQueue().removeBatchLoadableEntityKey(key);
		getBatchFetchQueue().removeSubselect(key);
		return entity;
	
public EntityEntryremoveEntry(java.lang.Object entity)
Remove an entity entry from the session cache

		return (EntityEntry) entityEntries.remove(entity);
	
public java.lang.ObjectremoveProxy(EntityKey key)
Remove a proxy from the session cache.

Additionally, ensure that any load optimization references such as batch or subselect loading get cleaned up as well.

param
key The key of the entity proxy to be removed
return
The proxy reference.

		if ( batchFetchQueue != null ) {
			batchFetchQueue.removeBatchLoadableEntityKey( key );
			batchFetchQueue.removeSubselect( key );
		}
		return proxiesByKey.remove( key );
	
public voidreplaceDelayedEntityIdentityInsertKeys(EntityKey oldKey, java.io.Serializable generatedId)

		Object entity = entitiesByKey.remove( oldKey );
		EntityEntry oldEntry = ( EntityEntry ) entityEntries.remove( entity );

		EntityKey newKey = new EntityKey( generatedId, oldEntry.getPersister(), getSession().getEntityMode() );
		addEntity( newKey, entity );
		addEntry(
				entity,
		        oldEntry.getStatus(),
		        oldEntry.getLoadedState(),
		        oldEntry.getRowId(),
		        generatedId,
		        oldEntry.getVersion(),
		        oldEntry.getLockMode(),
		        oldEntry.isExistsInDatabase(),
		        oldEntry.getPersister(),
		        oldEntry.isBeingReplicated(),
		        oldEntry.isLoadedWithLazyPropertiesUnfetched()
		);
	
public voidserialize(java.io.ObjectOutputStream oos)
Used by the owning session to explicitly control serialization of the persistence context.

param
oos The stream to which the persistence context should get written
throws
IOException serialization errors.

		log.trace( "serializing persistent-context" );

		oos.writeBoolean( hasNonReadOnlyEntities );

		oos.writeInt( entitiesByKey.size() );
		log.trace( "starting serialization of [" + entitiesByKey.size() + "] entitiesByKey entries" );
		Iterator itr = entitiesByKey.entrySet().iterator();
		while ( itr.hasNext() ) {
			Map.Entry entry = ( Map.Entry ) itr.next();
			( ( EntityKey ) entry.getKey() ).serialize( oos );
			oos.writeObject( entry.getValue() );
		}

		oos.writeInt( entitiesByUniqueKey.size() );
		log.trace( "starting serialization of [" + entitiesByUniqueKey.size() + "] entitiesByUniqueKey entries" );
		itr = entitiesByUniqueKey.entrySet().iterator();
		while ( itr.hasNext() ) {
			Map.Entry entry = ( Map.Entry ) itr.next();
			( ( EntityUniqueKey ) entry.getKey() ).serialize( oos );
			oos.writeObject( entry.getValue() );
		}

		oos.writeInt( proxiesByKey.size() );
		log.trace( "starting serialization of [" + proxiesByKey.size() + "] proxiesByKey entries" );
		itr = proxiesByKey.entrySet().iterator();
		while ( itr.hasNext() ) {
			Map.Entry entry = ( Map.Entry ) itr.next();
			( ( EntityKey ) entry.getKey() ).serialize( oos );
			oos.writeObject( entry.getValue() );
		}

		oos.writeInt( entitySnapshotsByKey.size() );
		log.trace( "starting serialization of [" + entitySnapshotsByKey.size() + "] entitySnapshotsByKey entries" );
		itr = entitySnapshotsByKey.entrySet().iterator();
		while ( itr.hasNext() ) {
			Map.Entry entry = ( Map.Entry ) itr.next();
			( ( EntityKey ) entry.getKey() ).serialize( oos );
			oos.writeObject( entry.getValue() );
		}

		oos.writeInt( entityEntries.size() );
		log.trace( "starting serialization of [" + entityEntries.size() + "] entityEntries entries" );
		itr = entityEntries.entrySet().iterator();
		while ( itr.hasNext() ) {
			Map.Entry entry = ( Map.Entry ) itr.next();
			oos.writeObject( entry.getKey() );
			( ( EntityEntry ) entry.getValue() ).serialize( oos );
		}

		oos.writeInt( collectionsByKey.size() );
		log.trace( "starting serialization of [" + collectionsByKey.size() + "] collectionsByKey entries" );
		itr = collectionsByKey.entrySet().iterator();
		while ( itr.hasNext() ) {
			Map.Entry entry = ( Map.Entry ) itr.next();
			( ( CollectionKey ) entry.getKey() ).serialize( oos );
			oos.writeObject( entry.getValue() );
		}

		oos.writeInt( collectionEntries.size() );
		log.trace( "starting serialization of [" + collectionEntries.size() + "] collectionEntries entries" );
		itr = collectionEntries.entrySet().iterator();
		while ( itr.hasNext() ) {
			Map.Entry entry = ( Map.Entry ) itr.next();
			oos.writeObject( entry.getKey() );
			( ( CollectionEntry ) entry.getValue() ).serialize( oos );
		}

		oos.writeInt( arrayHolders.size() );
		log.trace( "starting serialization of [" + arrayHolders.size() + "] arrayHolders entries" );
		itr = arrayHolders.entrySet().iterator();
		while ( itr.hasNext() ) {
			Map.Entry entry = ( Map.Entry ) itr.next();
			oos.writeObject( entry.getKey() );
			oos.writeObject( entry.getValue() );
		}

		oos.writeInt( nullifiableEntityKeys.size() );
		log.trace( "starting serialization of [" + nullifiableEntityKeys.size() + "] nullifiableEntityKeys entries" );
		itr = nullifiableEntityKeys.iterator();
		while ( itr.hasNext() ) {
			EntityKey entry = ( EntityKey ) itr.next();
			entry.serialize( oos );
		}
	
public voidsetEntryStatus(EntityEntry entry, Status status)

		entry.setStatus(status);
		setHasNonReadOnlyEnties(status);
	
public voidsetFlushing(boolean flushing)

		this.flushing = flushing;
	
private voidsetHasNonReadOnlyEnties(Status status)

		if ( status==Status.DELETED || status==Status.MANAGED || status==Status.SAVING ) {
			hasNonReadOnlyEntities = true;
		}
	
public voidsetReadOnly(java.lang.Object entity, boolean readOnly)

		EntityEntry entry = getEntry(entity);
		if (entry==null) {
			throw new TransientObjectException("Instance was not associated with the session");
		}
		entry.setReadOnly(readOnly, entity);
		hasNonReadOnlyEntities = hasNonReadOnlyEntities || !readOnly;
	
public java.lang.StringtoString()
Returns a string representation of the object.

return
a string representation of the object.

		return new StringBuffer()
				.append("PersistenceContext[entityKeys=")
				.append(entitiesByKey.keySet())
				.append(",collectionKeys=")
				.append(collectionsByKey.keySet())
				.append("]")
				.toString();
	
public java.lang.Objectunproxy(java.lang.Object maybeProxy)
Get the entity instance underlying the given proxy, throwing an exception if the proxy is uninitialized. If the given object is not a proxy, simply return the argument.

		if ( maybeProxy instanceof ElementWrapper ) {
			maybeProxy = ( (ElementWrapper) maybeProxy ).getElement();
		}
		
		if ( maybeProxy instanceof HibernateProxy ) {
			HibernateProxy proxy = (HibernateProxy) maybeProxy;
			LazyInitializer li = proxy.getHibernateLazyInitializer();
			if ( li.isUninitialized() ) {
				throw new PersistentObjectException(
						"object was an uninitialized proxy for " +
						li.getEntityName()
				);
			}
			return li.getImplementation(); //unwrap the object
		}
		else {
			return maybeProxy;
		}
	
public java.lang.ObjectunproxyAndReassociate(java.lang.Object maybeProxy)
Possibly unproxy the given reference and reassociate it with the current session.

param
maybeProxy The reference to be unproxied if it currently represents a proxy.
return
The unproxied instance.
throws
HibernateException

		if ( maybeProxy instanceof ElementWrapper ) {
			maybeProxy = ( (ElementWrapper) maybeProxy ).getElement();
		}
		
		if ( maybeProxy instanceof HibernateProxy ) {
			HibernateProxy proxy = (HibernateProxy) maybeProxy;
			LazyInitializer li = proxy.getHibernateLazyInitializer();
			reassociateProxy(li, proxy);
			return li.getImplementation(); //initialize + unwrap the object
		}
		else {
			return maybeProxy;
		}
	
public org.hibernate.collection.PersistentCollectionuseUnownedCollection(CollectionKey key)

		if (unownedCollections==null) {
			return null;
		}
		else {
			return (PersistentCollection) unownedCollections.remove(key);
		}