| Method from org.hibernate.event.def.DefaultLoadEventListener Detail: |
protected Object doLoad(LoadEvent event,
EntityPersister persister,
EntityKey keyToLoad,
LoadEventListener.LoadType options) {
if ( log.isTraceEnabled() ) {
log.trace(
"attempting to resolve: " +
MessageHelper.infoString( persister, event.getEntityId(), event.getSession().getFactory() )
);
}
Object entity = loadFromSessionCache( event, keyToLoad, options );
if ( entity == REMOVED_ENTITY_MARKER ) {
log.debug( "load request found matching entity in context, but it is scheduled for removal; returning null" );
return null;
}
if ( entity == INCONSISTENT_RTN_CLASS_MARKER ) {
log.debug( "load request found matching entity in context, but the matched entity was of an inconsistent return type; returning null" );
return null;
}
if ( entity != null ) {
if ( log.isTraceEnabled() ) {
log.trace(
"resolved object in session cache: " +
MessageHelper.infoString( persister, event.getEntityId(), event.getSession().getFactory() )
);
}
return entity;
}
entity = loadFromSecondLevelCache(event, persister, options);
if ( entity != null ) {
if ( log.isTraceEnabled() ) {
log.trace(
"resolved object in second-level cache: " +
MessageHelper.infoString( persister, event.getEntityId(), event.getSession().getFactory() )
);
}
return entity;
}
if ( log.isTraceEnabled() ) {
log.trace(
"object not resolved in any cache: " +
MessageHelper.infoString( persister, event.getEntityId(), event.getSession().getFactory() )
);
}
return loadFromDatasource(event, persister, keyToLoad, options);
}
Coordinates the efforts to load a given entity. First, an attempt is
made to load the entity from the session-level cache. If not found there,
an attempt is made to locate it in second-level cache. Lastly, an
attempt is made to load it directly from the datasource. |
protected Object load(LoadEvent event,
EntityPersister persister,
EntityKey keyToLoad,
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;
}
Perfoms the load of an entity. |
protected Object loadFromDatasource(LoadEvent event,
EntityPersister persister,
EntityKey keyToLoad,
LoadEventListener.LoadType options) {
final SessionImplementor source = event.getSession();
Object entity = persister.load(
event.getEntityId(),
event.getInstanceToLoad(),
event.getLockMode(),
source
);
if ( event.isAssociationFetch() && source.getFactory().getStatistics().isStatisticsEnabled() ) {
source.getFactory().getStatisticsImplementor().fetchEntity( event.getEntityClassName() );
}
return entity;
}
Performs the process of loading an entity from the configured
underlying datasource. |
protected Object loadFromSecondLevelCache(LoadEvent event,
EntityPersister persister,
LoadEventListener.LoadType options) {
final SessionImplementor source = event.getSession();
final boolean useCache = persister.hasCache()
&& source.getCacheMode().isGetEnabled()
&& event.getLockMode().lessThan(LockMode.READ);
if ( useCache ) {
final SessionFactoryImplementor factory = source.getFactory();
final CacheKey ck = new CacheKey(
event.getEntityId(),
persister.getIdentifierType(),
persister.getRootEntityName(),
source.getEntityMode(),
source.getFactory()
);
Object ce = persister.getCacheAccessStrategy().get( ck, source.getTimestamp() );
if ( factory.getStatistics().isStatisticsEnabled() ) {
if ( ce == null ) {
factory.getStatisticsImplementor().secondLevelCacheMiss(
persister.getCacheAccessStrategy().getRegion().getName()
);
}
else {
factory.getStatisticsImplementor().secondLevelCacheHit(
persister.getCacheAccessStrategy().getRegion().getName()
);
}
}
if ( ce != null ) {
CacheEntry entry = (CacheEntry) persister.getCacheEntryStructure().destructure( ce, factory );
// Entity was found in second-level cache...
return assembleCacheEntry(
entry,
event.getEntityId(),
persister,
event
);
}
}
return null;
}
Attempts to load the entity from the second-level cache. |
protected Object loadFromSessionCache(LoadEvent event,
EntityKey keyToLoad,
LoadEventListener.LoadType options) throws HibernateException {
SessionImplementor session = event.getSession();
Object old = session.getEntityUsingInterceptor( keyToLoad );
if ( old != null ) {
// this object was already loaded
EntityEntry oldEntry = session.getPersistenceContext().getEntry( old );
if ( options.isCheckDeleted() ) {
Status status = oldEntry.getStatus();
if ( status == Status.DELETED || status == Status.GONE ) {
return REMOVED_ENTITY_MARKER;
}
}
if ( options.isAllowNulls() ) {
EntityPersister persister = event.getSession().getFactory().getEntityPersister( event.getEntityClassName() );
if ( ! persister.isInstance( old, event.getSession().getEntityMode() ) ) {
return INCONSISTENT_RTN_CLASS_MARKER;
}
}
upgradeLock( old, oldEntry, event.getLockMode(), session );
}
return old;
}
Attempts to locate the entity in the session-level cache.
If allowed to return nulls, then if the entity happens to be found in
the session cache, we check the entity type for proper handling
of entity hierarchies.
If checkDeleted was set to true, then if the entity is found in the
session-level cache, it's current status within the session cache
is checked to see if it has previously been scheduled for deletion. |
protected Object lockAndLoad(LoadEvent event,
EntityPersister persister,
EntityKey keyToLoad,
LoadEventListener.LoadType options,
SessionImplementor source) {
SoftLock lock = null;
final CacheKey ck;
if ( persister.hasCache() ) {
ck = new CacheKey(
event.getEntityId(),
persister.getIdentifierType(),
persister.getRootEntityName(),
source.getEntityMode(),
source.getFactory()
);
lock = persister.getCacheAccessStrategy().lockItem( ck, null );
}
else {
ck = null;
}
Object entity;
try {
entity = load(event, persister, keyToLoad, options);
}
finally {
if ( persister.hasCache() ) {
persister.getCacheAccessStrategy().unlockItem( ck, lock );
}
}
return event.getSession().getPersistenceContext().proxyFor( persister, keyToLoad, entity );
}
If the class to be loaded has been configured with a cache, then lock
given id in that cache and then perform the load. |
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 for class " + persister.getEntityName() + ". 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;
}
}
Handle the given load event. |
protected Object proxyOrLoad(LoadEvent event,
EntityPersister persister,
EntityKey keyToLoad,
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);
}
}
}
}
Based on configured options, will either return a pre-existing proxy,
generate a new proxy, or perform an actual load. |