📄 defaultloadeventlistener.cs
字号:
using System;
using log4net;
using NHibernate.Cache;
using NHibernate.Cache.Entry;
using NHibernate.Engine;
using NHibernate.Impl;
using NHibernate.Persister.Entity;
using NHibernate.Proxy;
using NHibernate.Type;
namespace NHibernate.Event.Default
{
/// <summary>
/// Defines the default load event listeners used by hibernate for loading entities
/// in response to generated load events.
/// </summary>
[Serializable]
public class DefaultLoadEventListener : AbstractLockUpgradeEventListener, ILoadEventListener
{
private static readonly ILog log = LogManager.GetLogger(typeof(DefaultLoadEventListener));
public static readonly object RemovedEntityMarker = new object();
public static readonly object InconsistentRTNClassMarker= new object();
public static readonly LockMode DefaultLockMode = LockMode.None;
public virtual void OnLoad(LoadEvent @event, LoadType loadType)
{
ISessionImplementor source = @event.Session;
IEntityPersister persister;
if (@event.InstanceToLoad != null)
{
persister = source.GetEntityPersister(@event.InstanceToLoad); //the load() which takes an entity does not pass an entityName
@event.EntityClassName = @event.InstanceToLoad.GetType().FullName;
}
else
{
persister = source.Factory.GetEntityPersister(@event.EntityClassName);
}
if (persister == null)
{
throw new HibernateException("Unable to locate persister: " + @event.EntityClassName);
}
if (persister.IdentifierType.IsComponentType)
{
// 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
{
System.Type idClass = persister.IdentifierType.ReturnedClass;
if (idClass != null && !idClass.IsInstanceOfType(@event.EntityId))
{
throw new TypeMismatchException("Provided id of the wrong type. Expected: " + idClass + ", got " + @event.EntityId.GetType());
}
}
EntityKey keyToLoad = new EntityKey(@event.EntityId, persister, source.EntityMode);
try
{
if (loadType.IsNakedEntityReturned)
{
//do not return a proxy!
//(this option indicates we are initializing a proxy)
@event.Result = Load(@event, persister, keyToLoad, loadType);
}
else
{
//return a proxy if appropriate
if (@event.LockMode == LockMode.None)
{
@event.Result = ProxyOrLoad(@event, persister, keyToLoad, loadType);
}
else
{
@event.Result = LockAndLoad(@event, persister, keyToLoad, loadType, source);
}
}
}
catch (HibernateException e)
{
log.Info("Error performing load command", e);
throw;
}
}
/// <summary> Perfoms the load of an entity. </summary>
/// <returns> The loaded entity. </returns>
protected virtual object Load(LoadEvent @event, IEntityPersister persister, EntityKey keyToLoad, LoadType options)
{
if (@event.InstanceToLoad != null)
{
if (@event.Session.PersistenceContext.GetEntry(@event.InstanceToLoad) != null)
{
throw new PersistentObjectException("attempted to load into an instance that was already associated with the session: " + MessageHelper.InfoString(persister, @event.EntityId, @event.Session.Factory));
}
persister.SetIdentifier(@event.InstanceToLoad, @event.EntityId, @event.Session.EntityMode);
}
object entity = DoLoad(@event, persister, keyToLoad, options);
bool isOptionalInstance = @event.InstanceToLoad != null;
if (!options.IsAllowNulls || isOptionalInstance)
{
if (entity == null)
{
@event.Session.Factory.EntityNotFoundDelegate.HandleEntityNotFound(@event.EntityClassName, @event.EntityId);
}
}
if (isOptionalInstance && entity != @event.InstanceToLoad)
{
throw new NonUniqueObjectException(@event.EntityId, @event.EntityClassName);
}
return entity;
}
/// <summary>
/// Based on configured options, will either return a pre-existing proxy,
/// generate a new proxy, or perform an actual load.
/// </summary>
/// <returns> The result of the proxy/load operation.</returns>
protected virtual object ProxyOrLoad(LoadEvent @event, IEntityPersister persister, EntityKey keyToLoad, LoadType options)
{
if (log.IsDebugEnabled)
{
log.Debug("loading entity: " + MessageHelper.InfoString(persister, @event.EntityId, @event.Session.Factory));
}
if (!persister.HasProxy)
{
// this class has no proxies (so do a shortcut)
return Load(@event, persister, keyToLoad, options);
}
else
{
IPersistenceContext persistenceContext = @event.Session.PersistenceContext;
// 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);
}
}
}
}
/// <summary>
/// Given that there is a pre-existing proxy.
/// Initialize it if necessary; narrow if necessary.
/// </summary>
private object ReturnNarrowedProxy(LoadEvent @event, IEntityPersister persister, EntityKey keyToLoad, LoadType options, IPersistenceContext persistenceContext, object proxy)
{
log.Debug("entity proxy found in session cache");
ILazyInitializer li = ((INHibernateProxy)proxy).HibernateLazyInitializer;
if (li.Unwrap)
{
return li.GetImplementation();
}
object impl = null;
if (!options.IsAllowProxyCreation)
{
impl = Load(@event, persister, keyToLoad, options);
// NH Different behavior : NH-1252
if (impl == null && !options.IsAllowNulls)
{
@event.Session.Factory.EntityNotFoundDelegate.HandleEntityNotFound(persister.EntityName, keyToLoad.Identifier);
}
}
if (impl == null && !options.IsAllowProxyCreation && options.ExactPersister)
{
// NH Different behavior : NH-1252
return null;
}
return persistenceContext.NarrowProxy((INHibernateProxy)proxy, persister, keyToLoad, impl);
}
/// <summary>
/// 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.
/// </summary>
private object CreateProxyIfNecessary(LoadEvent @event, IEntityPersister persister, EntityKey keyToLoad, LoadType options, IPersistenceContext persistenceContext)
{
object existing = persistenceContext.GetEntity(keyToLoad);
if (existing != null)
{
// return existing object or initialized proxy (unless deleted)
log.Debug("entity found in session cache");
if (options.IsCheckDeleted)
{
EntityEntry entry = persistenceContext.GetEntry(existing);
Status status = entry.Status;
if (status == Status.Deleted || status == Status.Gone)
{
return null;
}
}
return existing;
}
else
{
log.Debug("creating new proxy for entity");
// return new uninitialized proxy
object proxy = persister.CreateProxy(@event.EntityId, @event.Session);
persistenceContext.BatchFetchQueue.AddBatchLoadableEntityKey(keyToLoad);
persistenceContext.AddProxy(keyToLoad, (INHibernateProxy)proxy);
return proxy;
}
}
/// <summary>
/// If the class to be loaded has been configured with a cache, then lock
/// given id in that cache and then perform the load.
/// </summary>
/// <returns> The loaded entity </returns>
protected virtual object LockAndLoad(LoadEvent @event, IEntityPersister persister, EntityKey keyToLoad, LoadType options, ISessionImplementor source)
{
ISoftLock sLock = null;
CacheKey ck;
if (persister.HasCache)
{
ck = new CacheKey(@event.EntityId, persister.IdentifierType, persister.RootEntityName, source.EntityMode, source.Factory);
sLock = persister.Cache.Lock(ck, null);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -