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

📄 defaultloadeventlistener.java

📁 hibernate-3.1.3-all-src.zip 面向对象的访问数据库工具
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
//$Id: DefaultLoadEventListener.java 7785 2005-08-08 23:24:44Z oneovthafew $
package org.hibernate.event.def;

import java.io.Serializable;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.HibernateException;
import org.hibernate.LockMode;
import org.hibernate.NonUniqueObjectException;
import org.hibernate.ObjectDeletedException;
import org.hibernate.ObjectNotFoundException;
import org.hibernate.PersistentObjectException;
import org.hibernate.cache.CacheConcurrencyStrategy;
import org.hibernate.cache.CacheKey;
import org.hibernate.cache.entry.CacheEntry;
import org.hibernate.engine.EntityEntry;
import org.hibernate.engine.EntityKey;
import org.hibernate.engine.PersistenceContext;
import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.engine.SessionImplementor;
import org.hibernate.engine.Status;
import org.hibernate.engine.TwoPhaseLoad;
import org.hibernate.engine.Versioning;
import org.hibernate.event.EventSource;
import org.hibernate.event.LoadEvent;
import org.hibernate.event.LoadEventListener;
import org.hibernate.event.PostLoadEvent;
import org.hibernate.event.PostLoadEventListener;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.pretty.MessageHelper;
import org.hibernate.proxy.HibernateProxy;
import org.hibernate.proxy.LazyInitializer;
import org.hibernate.type.Type;
import org.hibernate.type.TypeFactory;

/**
 * Defines the default load event listeners used by hibernate for loading entities
 * in response to generated load events.
 *
 * @author Steve Ebersole
 */
public class DefaultLoadEventListener extends AbstractLockUpgradeEventListener implements LoadEventListener {

	private static final Log log = LogFactory.getLog(DefaultLoadEventListener.class);

	public static final LockMode DEFAULT_LOCK_MODE = LockMode.NONE;

	/** 
	 * Handle the given load event.
	 *
	 * @param event The load event to be handled.
	 * @return The result (i.e., the loaded entity).
	 * @throws HibernateException
	 */
	public void onLoad(LoadEvent event, LoadEventListener.LoadType loadType) throws HibernateException {

		final SessionImplementor source = event.getSession();

		EntityPersister persister;
		if ( event.getInstanceToLoad() != null ) {
			persister = source.getEntityPersister( null, event.getInstanceToLoad() ); //the load() which takes an entity does not pass an entityName
			event.setEntityClassName( event.getInstanceToLoad().getClass().getName() );
		}
		else {
			persister = source.getFactory().getEntityPersister( event.getEntityClassName() );
		}

		if ( persister == null ) {
			throw new HibernateException( 
					"Unable to locate persister: " + 
					event.getEntityClassName() 
				);
		}
		
		EntityKey keyToLoad = new EntityKey( event.getEntityId(), persister, source.getEntityMode()  );

		try {
			if ( loadType.isNakedEntityReturned() ) {
				//do not return a proxy!
				//(this option indicates we are initializing a proxy)
				event.setResult( load(event, persister, keyToLoad, loadType) );
			}
			else {
				//return a proxy if appropriate
				if ( event.getLockMode() == LockMode.NONE ) {
					event.setResult( proxyOrLoad(event, persister, keyToLoad, loadType) );
				}
				else {
					event.setResult( lockAndLoad(event, persister, keyToLoad, loadType, source) );
				}
			}
		}
		catch(HibernateException e) {
			log.info("Error performing load command", e);
			throw e;
		}
	}

	/**
	 * Perfoms the load of an entity.
	 *
	 * @return The loaded entity.
	 * @throws HibernateException
	 */
	protected Object load(
		final LoadEvent event, 
		final EntityPersister persister, 
		final EntityKey keyToLoad, 
		final LoadEventListener.LoadType options)
	throws HibernateException {
	
		if ( event.getInstanceToLoad() != null ) {
			if ( event.getSession().getPersistenceContext().getEntry( event.getInstanceToLoad() ) != null ) {
				throw new PersistentObjectException(
						"attempted to load into an instance that was already associated with the session: " +
						MessageHelper.infoString( persister, event.getEntityId(), event.getSession().getFactory() )
					);
			}
			persister.setIdentifier( event.getInstanceToLoad(), event.getEntityId(), event.getSession().getEntityMode() );
		}

		Object entity = doLoad(event, persister, keyToLoad, options);
		
		boolean isOptionalInstance = event.getInstanceToLoad() != null;
		
		if ( !options.isAllowNulls() || isOptionalInstance ) {
			ObjectNotFoundException.throwIfNull( entity, event.getEntityId(), event.getEntityClassName() );
		}

		if ( isOptionalInstance && entity != event.getInstanceToLoad() ) {
			throw new NonUniqueObjectException( event.getEntityId(), event.getEntityClassName() );
		}

		return entity;
	}

	/** 
	 * Based on configured options, will either return a pre-existing proxy,
	 * generate a new proxy, or perform an actual load.
	 *
	 * @return The result of the proxy/load operation.
	 * @throws HibernateException
	 */
	protected Object proxyOrLoad(
		final LoadEvent event, 
		final EntityPersister persister,
		final EntityKey keyToLoad, 
		final LoadEventListener.LoadType options) 
	throws HibernateException {
		
		if ( log.isTraceEnabled() ) {
			log.trace(
					"loading entity: " + 
					MessageHelper.infoString( persister, event.getEntityId(), event.getSession().getFactory() )
				);
		}

		if ( !persister.hasProxy() ) {
			// this class has no proxies (so do a shortcut)
			return load(event, persister, keyToLoad, options);
		}
		else {
			final PersistenceContext persistenceContext = event.getSession().getPersistenceContext();

			// look for a proxy
			Object proxy = persistenceContext.getProxy(keyToLoad);
			if ( proxy != null ) {
				return returnNarrowedProxy( event, persister, keyToLoad, options, persistenceContext, proxy );
			}
			else {
				if ( options.isAllowProxyCreation() ) {
					return createProxyIfNecessary( event, persister, keyToLoad, options, persistenceContext );
				}
				else {
					// return a newly loaded object
					return load(event, persister, keyToLoad, options);
				}
			}
			
		}
	}

	/**
	 * Given that there is a pre-existing proxy.
	 * Initialize it if necessary; narrow if necessary.
	 */
	private Object returnNarrowedProxy(
			final LoadEvent event, 
			final EntityPersister persister, 
			final EntityKey keyToLoad, 
			final LoadEventListener.LoadType options, 
			final PersistenceContext persistenceContext, 
			final Object proxy
	) {
		log.trace("entity proxy found in session cache");
		LazyInitializer li = ( (HibernateProxy) proxy ).getHibernateLazyInitializer();
		if ( li.isUnwrap() ) {
			return li.getImplementation();
		}
		// return existing or narrowed proxy
		Object impl = options.isAllowProxyCreation() ?
				null : load(event, persister, keyToLoad, options);
		return persistenceContext.narrowProxy( proxy, persister, keyToLoad, impl );
	}
	
	/**
	 * Given that there is no pre-existing proxy.
	 * Check if the entity is already loaded. If it is, return the entity,
	 * otherwise create and return a 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);
				throwObjectDeletedIfNecessary(event, entry);
			}
			return existing;
		}
		else {
			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;
		}
	}

	/** 
	 * If the class to be loaded has been configured with a cache, then lock
	 * given id in that cache and then perform the load.
	 *
	 * @return The loaded entity
	 * @throws HibernateException
	 */
	protected Object lockAndLoad(
		final LoadEvent event, 
		final EntityPersister persister,
		final EntityKey keyToLoad, 
		final LoadEventListener.LoadType options,
		final SessionImplementor source) 
	throws HibernateException {
		
		CacheConcurrencyStrategy.SoftLock lock = null;
		final CacheKey ck;
		if ( persister.hasCache() ) {
			ck = new CacheKey( 
					event.getEntityId(), 
					persister.getIdentifierType(), 
					persister.getRootEntityName(), 
					source.getEntityMode(), 
					source.getFactory() 
				);
			lock = persister.getCache().lock(ck, null );
		}
		else {
			ck = null;
		}

		Object entity;
		try {
			entity = load(event, persister, keyToLoad, options);
		}
		finally {
			if ( persister.hasCache() ) {
				persister.getCache().release(ck, lock );
			}
		}

		Object proxy = event.getSession().getPersistenceContext()
				.proxyFor( persister, keyToLoad, entity );
		

⌨️ 快捷键说明

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