📄 defaultloadeventlistener.java
字号:
//$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 + -