1 package org.hibernate.event.def; 3 4 import java.io.Serializable ; 5 6 import org.apache.commons.logging.Log; 7 import org.apache.commons.logging.LogFactory; 8 import org.hibernate.HibernateException; 9 import org.hibernate.LockMode; 10 import org.hibernate.NonUniqueObjectException; 11 import org.hibernate.ObjectDeletedException; 12 import org.hibernate.ObjectNotFoundException; 13 import org.hibernate.PersistentObjectException; 14 import org.hibernate.cache.CacheConcurrencyStrategy; 15 import org.hibernate.cache.CacheKey; 16 import org.hibernate.cache.entry.CacheEntry; 17 import org.hibernate.engine.EntityEntry; 18 import org.hibernate.engine.EntityKey; 19 import org.hibernate.engine.PersistenceContext; 20 import org.hibernate.engine.SessionFactoryImplementor; 21 import org.hibernate.engine.SessionImplementor; 22 import org.hibernate.engine.Status; 23 import org.hibernate.engine.TwoPhaseLoad; 24 import org.hibernate.engine.Versioning; 25 import org.hibernate.event.EventSource; 26 import org.hibernate.event.LoadEvent; 27 import org.hibernate.event.LoadEventListener; 28 import org.hibernate.event.PostLoadEvent; 29 import org.hibernate.persister.entity.EntityPersister; 30 import org.hibernate.pretty.MessageHelper; 31 import org.hibernate.proxy.HibernateProxy; 32 import org.hibernate.proxy.LazyInitializer; 33 import org.hibernate.type.Type; 34 import org.hibernate.type.TypeFactory; 35 36 42 public class DefaultLoadEventListener extends AbstractLockUpgradeEventListener implements LoadEventListener { 43 44 private static final Log log = LogFactory.getLog(DefaultLoadEventListener.class); 45 46 public static final LockMode DEFAULT_LOCK_MODE = LockMode.NONE; 47 48 55 public Object onLoad(LoadEvent event, LoadEventListener.LoadType loadType) throws HibernateException { 56 57 final SessionImplementor source = event.getSession(); 58 59 EntityPersister persister; 60 if ( event.getInstanceToLoad() != null ) { 61 persister = source.getEntityPersister( null, event.getInstanceToLoad() ); event.setEntityClassName( event.getInstanceToLoad().getClass().getName() ); 63 } 64 else { 65 persister = source.getFactory().getEntityPersister( event.getEntityClassName() ); 66 } 67 68 if ( persister == null ) { 69 throw new HibernateException( "Unable to locate persister: " + event.getEntityClassName() ); 70 } 71 72 EntityKey keyToLoad = new EntityKey( event.getEntityId(), persister, source.getEntityMode() ); 73 74 try { 75 if ( loadType.isNakedEntityReturned() ) { 76 return load(event, persister, keyToLoad, loadType); 79 } 80 else { 81 return event.getLockMode() == LockMode.NONE ? 83 proxyOrLoad(event, persister, keyToLoad, loadType) : 84 lockAndLoad(event, persister, keyToLoad, loadType, source); 85 } 86 } 87 catch(HibernateException e) { 88 log.info("Error performing load command", e); 89 throw e; 90 } 91 } 92 93 99 protected Object load( 100 final LoadEvent event, 101 final EntityPersister persister, 102 final EntityKey keyToLoad, 103 final LoadEventListener.LoadType options) 104 throws HibernateException { 105 106 if ( event.getInstanceToLoad() != null ) { 107 if ( event.getSession().getPersistenceContext().getEntry( event.getInstanceToLoad() ) != null ) { 108 throw new PersistentObjectException( 109 "attempted to load into an instance that was already associated with the session: " + 110 MessageHelper.infoString( persister, event.getEntityId(), event.getSession().getFactory() ) 111 ); 112 } 113 persister.setIdentifier( event.getInstanceToLoad(), event.getEntityId(), event.getSession().getEntityMode() ); 114 } 115 116 Object entity = doLoad(event, persister, keyToLoad, options); 117 118 boolean isOptionalInstance = event.getInstanceToLoad() != null; 119 120 if ( !options.isAllowNulls() || isOptionalInstance ) { 121 ObjectNotFoundException.throwIfNull( entity, event.getEntityId(), event.getEntityClassName() ); 122 } 123 124 if ( isOptionalInstance && entity != event.getInstanceToLoad() ) { 125 throw new NonUniqueObjectException( event.getEntityId(), event.getEntityClassName() ); 126 } 127 128 return entity; 129 } 130 131 138 protected Object proxyOrLoad( 139 final LoadEvent event, 140 final EntityPersister persister, 141 final EntityKey keyToLoad, 142 final LoadEventListener.LoadType options) 143 throws HibernateException { 144 145 if ( log.isTraceEnabled() ) { 146 log.trace( 147 "loading entity: " + 148 MessageHelper.infoString( persister, event.getEntityId(), event.getSession().getFactory() ) 149 ); 150 } 151 152 if ( !persister.hasProxy() ) { 153 return load(event, persister, keyToLoad, options); 155 } 156 else { 157 final PersistenceContext persistenceContext = event.getSession().getPersistenceContext(); 158 159 Object proxy = persistenceContext.getProxy(keyToLoad); 161 if ( proxy != null ) { 162 return returnNarrowedProxy( event, persister, keyToLoad, options, persistenceContext, proxy ); 163 } 164 else { 165 if ( options.isAllowProxyCreation() ) { 166 return createProxyIfNecessary( event, persister, keyToLoad, options, persistenceContext ); 167 } 168 else { 169 return load(event, persister, keyToLoad, options); 171 } 172 } 173 174 } 175 } 176 177 181 private Object returnNarrowedProxy( 182 final LoadEvent event, 183 final EntityPersister persister, 184 final EntityKey keyToLoad, 185 final LoadEventListener.LoadType options, 186 final PersistenceContext persistenceContext, 187 final Object proxy 188 ) { 189 log.trace("entity proxy found in session cache"); 190 LazyInitializer li = ( (HibernateProxy) proxy ).getHibernateLazyInitializer(); 191 if ( li.isUnwrap() ) { 192 return li.getImplementation(); 193 } 194 Object impl = options.isAllowProxyCreation() ? 196 null : load(event, persister, keyToLoad, options); 197 return persistenceContext.narrowProxy( proxy, persister, keyToLoad, impl ); 198 } 199 200 205 private Object createProxyIfNecessary( 206 final LoadEvent event, 207 final EntityPersister persister, 208 final EntityKey keyToLoad, 209 final LoadEventListener.LoadType options, 210 final PersistenceContext persistenceContext 211 ) { 212 Object existing = persistenceContext.getEntity(keyToLoad); 213 if ( existing != null ) { 214 log.trace("entity found in session cache"); 216 if ( options.isCheckDeleted() ) { 217 EntityEntry entry = persistenceContext.getEntry(existing); 218 throwObjectDeletedIfNecessary(event, entry); 219 } 220 return existing; 221 } 222 else { 223 log.trace("creating new proxy for entity"); 224 Object proxy = persister.createProxy( event.getEntityId(), event.getSession() ); 226 persistenceContext.getBatchFetchQueue().addBatchLoadableEntityKey(keyToLoad); 227 persistenceContext.addProxy(keyToLoad, proxy); 228 return proxy; 229 } 230 } 231 232 239 protected Object lockAndLoad( 240 final LoadEvent event, 241 final EntityPersister persister, 242 final EntityKey keyToLoad, 243 final LoadEventListener.LoadType options, 244 final SessionImplementor source) 245 throws HibernateException { 246 247 CacheConcurrencyStrategy.SoftLock lock = null; 248 final CacheKey ck; 249 if ( persister.hasCache() ) { 250 ck = new CacheKey( 251 event.getEntityId(), 252 persister.getIdentifierType(), 253 persister.getRootEntityName(), 254 source.getEntityMode(), 255 source.getFactory() 256 ); 257 lock = persister.getCache().lock(ck, null ); 258 } 259 else { 260 ck = null; 261 } 262 263 Object entity; 264 try { 265 entity = load(event, persister, keyToLoad, options); 266 } 267 finally { 268 if ( persister.hasCache() ) { 269 persister.getCache().release(ck, lock ); 270 } 271 } 272 273 Object proxy = event.getSession().getPersistenceContext() 274 .proxyFor( persister, keyToLoad, entity ); 275 276 return proxy; 277 } 278 279 280 289 protected Object doLoad( 290 final LoadEvent event, 291 final EntityPersister persister, 292 final EntityKey keyToLoad, 293 final LoadEventListener.LoadType options) 294 throws HibernateException { 295 296 if ( log.isTraceEnabled() ) { 297 log.trace( 298 "attempting to resolve: " + 299 MessageHelper.infoString( persister, event.getEntityId(), event.getSession().getFactory() ) 300 ); 301 } 302 303 Object entity = loadFromSessionCache(event, keyToLoad, options); 304 if ( entity != null ) { 305 if ( log.isTraceEnabled() ) { 306 log.trace( 307 "resolved object in session cache: " + 308 MessageHelper.infoString( persister, event.getEntityId(), event.getSession().getFactory() ) 309 ); 310 } 311 return entity; 312 } 313 314 320 321 entity = loadFromSecondLevelCache(event, persister, options); 322 if ( entity != null ) { 323 if ( log.isTraceEnabled() ) { 324 log.trace( 325 "resolved object in second-level cache: " + 326 MessageHelper.infoString( persister, event.getEntityId(), event.getSession().getFactory() ) 327 ); 328 } 329 return entity; 330 } 331 332 if ( log.isTraceEnabled() ) { 333 log.trace( 334 "object not resolved in any cache: " + 335 MessageHelper.infoString( persister, event.getEntityId(), event.getSession().getFactory() ) 336 ); 337 } 338 339 return loadFromDatasource(event, persister, keyToLoad, options); 340 } 341 342 349 protected Object loadFromDatasource( 350 final LoadEvent event, 351 final EntityPersister persister, 352 final EntityKey keyToLoad, 353 final LoadEventListener.LoadType options) 354 throws HibernateException { 355 356 final SessionImplementor source = event.getSession(); 357 358 Object entity = persister.load( 359 event.getEntityId(), 360 event.getInstanceToLoad(), 361 event.getLockMode(), 362 source 363 ); 364 365 369 370 if ( event.isAssociationFetch() && source.getFactory().getStatistics().isStatisticsEnabled() ) { 371 source.getFactory().getStatisticsImplementor().fetchEntity( event.getEntityClassName() ); 372 } 373 374 return entity; 375 } 376 377 386 protected Object loadFromSessionCache( 387 final LoadEvent event, 388 final EntityKey keyToLoad, 389 final LoadEventListener.LoadType options) 390 throws HibernateException { 391 392 SessionImplementor session = event.getSession(); 393 Object old = session.getEntityUsingInterceptor(keyToLoad); 394 if ( old != null ) { 395 EntityEntry oldEntry = session.getPersistenceContext().getEntry(old); 397 if ( options.isCheckDeleted() ) { 398 throwObjectDeletedIfNecessary( event, oldEntry ); 399 } 400 upgradeLock( old, oldEntry, event.getLockMode(), session ); 401 } 402 return old; 403 } 404 405 private void throwObjectDeletedIfNecessary(LoadEvent event, EntityEntry oldEntry) { 406 Status status = oldEntry.getStatus(); 407 if ( status == Status.DELETED || status == Status.GONE ) { 408 throw new ObjectDeletedException( 409 "The object with that id was deleted", 410 event.getEntityId(), 411 event.getEntityClassName() 412 ); 413 } 414 } 415 416 422 protected Object loadFromSecondLevelCache( 423 final LoadEvent event, 424 final EntityPersister persister, 425 final LoadEventListener.LoadType options) 426 throws HibernateException { 427 428 final SessionImplementor source = event.getSession(); 429 430 final boolean useCache = persister.hasCache() && 431 source.getCacheMode().isGetEnabled() && 432 event.getLockMode().lessThan(LockMode.READ); 433 434 if (useCache) { 435 436 final SessionFactoryImplementor factory = source.getFactory(); 437 438 final CacheKey ck = new CacheKey( 439 event.getEntityId(), 440 persister.getIdentifierType(), 441 persister.getRootEntityName(), 442 source.getEntityMode(), 443 source.getFactory() 444 ); 445 Object ce = persister.getCache() 446 .get( ck, source.getTimestamp() ); 447 448 if ( factory.getStatistics().isStatisticsEnabled() ) { 449 if (ce==null) { 450 factory.getStatisticsImplementor().secondLevelCacheMiss( 451 persister.getCache().getRegionName() 452 ); 453 } 454 else { 455 factory.getStatisticsImplementor().secondLevelCacheHit( 456 persister.getCache().getRegionName() 457 ); 458 } 459 } 460 461 if ( ce != null ) { 462 463 CacheEntry entry = (CacheEntry) persister.getCacheEntryStructure() 464 .destructure(ce, factory); 465 466 return assembleCacheEntry( 468 entry, 469 event.getEntityId(), 470 persister, 471 event 472 ); 473 } 474 } 475 476 return null; 477 } 478 479 private Object assembleCacheEntry( 480 final CacheEntry entry, 481 final Serializable id, 482 final EntityPersister persister, 483 final LoadEvent event) 484 throws HibernateException { 485 486 final Object optionalObject = event.getInstanceToLoad(); 487 final EventSource session = event.getSession(); 488 final SessionFactoryImplementor factory = session.getFactory(); 489 490 if ( log.isTraceEnabled() ) log.trace( 491 "resolved object in second-level cache: " + 492 MessageHelper.infoString( persister, id, factory ) 493 ); 494 495 EntityPersister subclassPersister = factory.getEntityPersister( entry.getSubclass() ); 496 Object result = optionalObject == null ? 497 session.instantiate( subclassPersister, id ) : optionalObject; 498 499 TwoPhaseLoad.addUninitializedEntity( 501 new EntityKey( id, subclassPersister, session.getEntityMode() ), 502 result, 503 subclassPersister, 504 LockMode.NONE, 505 entry.areLazyPropertiesUnfetched(), 506 session 507 ); 508 509 Type[] types = subclassPersister.getPropertyTypes(); 510 Object [] values = entry.assemble( result, id, subclassPersister, session.getInterceptor(), session ); TypeFactory.deepCopy( 512 values, 513 types, 514 subclassPersister.getPropertyUpdateability(), 515 values, 516 session 517 ); 518 519 Object version = Versioning.getVersion( values, subclassPersister ); 520 if ( log.isTraceEnabled() ) log.trace( "Cached Version: " + version ); 521 522 final PersistenceContext persistenceContext = session.getPersistenceContext(); 523 persistenceContext.addEntry( 524 result, 525 Status.MANAGED, 526 values, 527 null, 528 id, 529 version, 530 LockMode.NONE, 531 true, 532 subclassPersister, 533 false, 534 entry.areLazyPropertiesUnfetched() 535 ); 536 subclassPersister.afterInitialize( result, entry.areLazyPropertiesUnfetched(), session ); 537 persistenceContext.initializeNonLazyCollections(); 538 541 PostLoadEvent postLoadEvent = new PostLoadEvent(session).setEntity(result) 544 .setId(id).setPersister(persister); 545 session.getListeners().getPostLoadEventListener().onPostLoad(postLoadEvent); 546 547 return result; 548 } 549 550 } 551 | Popular Tags |