📄 defaultloadeventlistener.java
字号:
//$Id: DefaultLoadEventListener.java 11398 2007-04-10 14:54:07Z steve.ebersole@jboss.com $package org.hibernate.event.def;import java.io.Serializable;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.hibernate.HibernateException;import org.hibernate.LockMode;import org.hibernate.NonUniqueObjectException;import org.hibernate.PersistentObjectException;import org.hibernate.TypeMismatchException;import org.hibernate.EntityMode;import org.hibernate.cache.CacheKey;import org.hibernate.cache.access.SoftLock;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 { public static final Object REMOVED_ENTITY_MARKER = new Object(); public static final Object INCONSISTENT_RTN_CLASS_MARKER = new Object(); public static final LockMode DEFAULT_LOCK_MODE = LockMode.NONE; private static final Logger log = LoggerFactory.getLogger(DefaultLoadEventListener.class); /** * Handle the given load event. * * @param event The load event to be handled. * @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() ); } if ( persister.getIdentifierType().isComponentType() && EntityMode.DOM4J == event.getSession().getEntityMode() ) { // skip this check for composite-ids relating to dom4j entity-mode; // alternatively, we could add a check to make sure the incoming id value is // an instance of Element... } else { Class idClass = persister.getIdentifierType().getReturnedClass(); if ( idClass != null && ! idClass.isInstance( event.getEntityId() ) ) { throw new TypeMismatchException( "Provided id of the wrong type. Expected: " + idClass + ", got " + event.getEntityId().getClass() ); } } 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. * * @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 * @return The loaded entity. * @throws HibernateException */ protected Object load( final LoadEvent event, final EntityPersister persister, final EntityKey keyToLoad, final LoadEventListener.LoadType options) { 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 ) { if ( entity == null ) { event.getSession().getFactory().getEntityNotFoundDelegate().handleEntityNotFound( event.getEntityClassName(), event.getEntityId() ); } } 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. * * @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 * @return The result of the proxy/load operation. */ protected Object proxyOrLoad( final LoadEvent event, final EntityPersister persister, final EntityKey keyToLoad, final LoadEventListener.LoadType options) { 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 a proxy, initialize it and/or narrow it provided either * is necessary. * * @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 * @param proxy The proxy to narrow * @return The created/existing proxy */ 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(); } Object impl = null; if ( !options.isAllowProxyCreation() ) { impl = load( event, persister, keyToLoad, options ); if ( impl == null ) { event.getSession().getFactory().getEntityNotFoundDelegate().handleEntityNotFound( persister.getEntityName(), keyToLoad.getIdentifier()); } } return persistenceContext.narrowProxy( proxy, persister, keyToLoad, impl ); } /** * 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; } 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. * * @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 source The originating session * @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) { SoftLock lock = null; final CacheKey ck; if ( persister.hasCache() ) { ck = new CacheKey( event.getEntityId(),
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -