⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 statefulpersistencecontext.java

📁 一个Java持久层类库
💻 JAVA
📖 第 1 页 / 共 4 页
字号:
// $Id: StatefulPersistenceContext.java 11490 2007-05-09 01:43:11Z steve.ebersole@jboss.com $package org.hibernate.engine;import java.io.IOException;import java.io.InvalidObjectException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.io.Serializable;import java.util.ArrayList;import java.util.HashMap;import java.util.HashSet;import java.util.Iterator;import java.util.List;import java.util.Map;import org.apache.commons.collections.map.ReferenceMap;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.hibernate.AssertionFailure;import org.hibernate.Hibernate;import org.hibernate.HibernateException;import org.hibernate.LockMode;import org.hibernate.MappingException;import org.hibernate.NonUniqueObjectException;import org.hibernate.PersistentObjectException;import org.hibernate.TransientObjectException;import org.hibernate.engine.loading.LoadContexts;import org.hibernate.pretty.MessageHelper;import org.hibernate.collection.PersistentCollection;import org.hibernate.persister.collection.CollectionPersister;import org.hibernate.persister.entity.EntityPersister;import org.hibernate.proxy.HibernateProxy;import org.hibernate.proxy.LazyInitializer;import org.hibernate.tuple.ElementWrapper;import org.hibernate.util.IdentityMap;import org.hibernate.util.MarkerObject;/** * A <tt>PersistenceContext</tt> represents the state of persistent "stuff" which * Hibernate is tracking.  This includes persistent entities, collections, * as well as proxies generated. * </p> * 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 */public class StatefulPersistenceContext implements PersistenceContext {	public static final Object NO_ROW = new MarkerObject( "NO_ROW" );	private static final Logger log = LoggerFactory.getLogger( StatefulPersistenceContext.class );	private static final Logger PROXY_WARN_LOG = LoggerFactory.getLogger( StatefulPersistenceContext.class.getName() + ".ProxyWarnLog" );	private static final int INIT_COLL_SIZE = 8;	private SessionImplementor session;		// Loaded entity instances, by EntityKey	private Map entitiesByKey;	// Loaded entity instances, by EntityUniqueKey	private Map entitiesByUniqueKey;		// Identity map of EntityEntry instances, by the entity instance	private Map entityEntries;		// Entity proxies, by EntityKey	private Map proxiesByKey;		// Snapshots of current database state for entities	// that have *not* been loaded	private Map entitySnapshotsByKey;		// Identity map of array holder ArrayHolder instances, by the array instance	private Map arrayHolders;		// Identity map of CollectionEntry instances, by the collection wrapper	private Map collectionEntries;		// Collection wrappers, by the CollectionKey	private Map collectionsByKey; //key=CollectionKey, value=PersistentCollection		// Set of EntityKeys of deleted objects	private HashSet nullifiableEntityKeys;		// properties that we have tried to load, and not found in the database	private HashSet nullAssociations;		// A list of collection wrappers that were instantiating during result set	// processing, that we will need to initialize at the end of the query	private List nonlazyCollections;		// A container for collections we load up when the owning entity is not	// yet loaded ... for now, this is purely transient!	private Map unownedCollections;		private int cascading = 0;	private int loadCounter = 0;	private boolean flushing = false;		private boolean hasNonReadOnlyEntities = false;	private LoadContexts loadContexts;	private BatchFetchQueue batchFetchQueue;	/**	 * Constructs a PersistentContext, bound to the given session.	 *	 * @param session The session "owning" this context.	 */	public StatefulPersistenceContext(SessionImplementor session) {		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();	}	private void initTransientState() {		nullAssociations = new HashSet( INIT_COLL_SIZE );		nonlazyCollections = new ArrayList( INIT_COLL_SIZE );	}	public boolean isStateless() {		return false;	}		public SessionImplementor getSession() {		return session;	}	public LoadContexts getLoadContexts() {		if ( loadContexts == null ) {			loadContexts = new LoadContexts( this );		}		return loadContexts;	}	public void addUnownedCollection(CollectionKey key, PersistentCollection collection) {		if (unownedCollections==null) {			unownedCollections = new HashMap(8);		}		unownedCollections.put(key, collection);	}		public PersistentCollection useUnownedCollection(CollectionKey key) {		if (unownedCollections==null) {			return null;		}		else {			return (PersistentCollection) unownedCollections.remove(key);		}	}		/**	 * Get the <tt>BatchFetchQueue</tt>, instantiating one if	 * necessary.	 */	public BatchFetchQueue getBatchFetchQueue() {		if (batchFetchQueue==null) {			batchFetchQueue = new BatchFetchQueue(this);		}		return batchFetchQueue;	}	public void clear() {		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();		}	}		public boolean hasNonReadOnlyEntities() {		return hasNonReadOnlyEntities;	}		public void setEntryStatus(EntityEntry entry, Status status) {		entry.setStatus(status);		setHasNonReadOnlyEnties(status);	}		private void setHasNonReadOnlyEnties(Status status) {		if ( status==Status.DELETED || status==Status.MANAGED || status==Status.SAVING ) {			hasNonReadOnlyEntities = true;		}	}	public void afterTransactionCompletion() {		// Downgrade locks		Iterator iter = entityEntries.values().iterator();		while ( iter.hasNext() ) {			( (EntityEntry) iter.next() ).setLockMode(LockMode.NONE);		}	}	/**	 * Get the current state of the entity as known to the underlying	 * database, or null if there is no corresponding row 	 */	public Object[] getDatabaseSnapshot(Serializable id, EntityPersister persister)	throws HibernateException {		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 Object[] getNaturalIdSnapshot(Serializable id, EntityPersister persister)	throws HibernateException {		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 );		}	}	/**	 * Retrieve the cached database snapshot for the requested entity key.	 * <p/>	 * This differs from {@link #getDatabaseSnapshot} is two important respects:<ol>	 * <li>no snapshot is obtained from the database if not already cached</li>	 * <li>an entry of {@link #NO_ROW} here is interpretet as an exception</li>	 * </ol>	 * @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}.	 */	public Object[] getCachedDatabaseSnapshot(EntityKey key) {		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 void removeDatabaseSnapshot(EntityKey key) {		entitySnapshotsByKey.remove(key);	}*/	public void addEntity(EntityKey key, Object entity) {		entitiesByKey.put(key, entity);		getBatchFetchQueue().removeBatchLoadableEntityKey(key);	}	/**	 * Get the entity instance associated with the given 	 * <tt>EntityKey</tt>	 */	public Object getEntity(EntityKey key) {		return entitiesByKey.get(key);	}	public boolean containsEntity(EntityKey key) {		return entitiesByKey.containsKey(key);	}	/**	 * Remove an entity from the session cache, also clear	 * up other state associated with the entity, all except	 * for the <tt>EntityEntry</tt>	 */	public Object removeEntity(EntityKey key) {		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;	}	/**	 * Get an entity cached by unique key	 */	public Object getEntity(EntityUniqueKey euk) {		return entitiesByUniqueKey.get(euk);	}	/**	 * Add an entity to the cache by unique key	 */	public void addEntity(EntityUniqueKey euk, Object entity) {		entitiesByUniqueKey.put(euk, 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.	 */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -