private Object assembleCacheEntry( final CacheEntry entry, final Serializable id, final EntityPersister persister, final LoadEvent event) throws HibernateException { final Object optionalObject = event.getInstanceToLoad(); final EventSource session = event.getSession(); final SessionFactoryImplementor factory = session.getFactory(); if (log.isTraceEnabled()) { log.trace( "assembling entity from second-level cache: " + MessageHelper.infoString(persister, id, factory)); } EntityPersister subclassPersister = factory.getEntityPersister(entry.getSubclass()); Object result = optionalObject == null ? session.instantiate(subclassPersister, id) : optionalObject; // make it circular-reference safe TwoPhaseLoad.addUninitializedCachedEntity( new EntityKey(id, subclassPersister, session.getEntityMode()), result, subclassPersister, LockMode.NONE, entry.areLazyPropertiesUnfetched(), entry.getVersion(), session); Type[] types = subclassPersister.getPropertyTypes(); Object[] values = entry.assemble( result, id, subclassPersister, session.getInterceptor(), session); // intializes result by side-effect TypeFactory.deepCopy( values, types, subclassPersister.getPropertyUpdateability(), values, session); Object version = Versioning.getVersion(values, subclassPersister); if (log.isTraceEnabled()) log.trace("Cached Version: " + version); final PersistenceContext persistenceContext = session.getPersistenceContext(); persistenceContext.addEntry( result, Status.MANAGED, values, null, id, version, LockMode.NONE, true, subclassPersister, false, entry.areLazyPropertiesUnfetched()); subclassPersister.afterInitialize(result, entry.areLazyPropertiesUnfetched(), session); persistenceContext.initializeNonLazyCollections(); // upgrade the lock if necessary: // lock(result, lockMode); // PostLoad is needed for EJB3 // TODO: reuse the PostLoadEvent... PostLoadEvent postLoadEvent = new PostLoadEvent(session).setEntity(result).setId(id).setPersister(persister); PostLoadEventListener[] listeners = session.getListeners().getPostLoadEventListeners(); for (int i = 0; i < listeners.length; i++) { listeners[i].onPostLoad(postLoadEvent); } return result; }
/** * Perform the second step of 2-phase load. Fully initialize the entity instance. * * <p>After processing a JDBC result set, we "resolve" all the associations between the entities * which were instantiated and had their state "hydrated" into an array */ public static void initializeEntity( final Object entity, final boolean readOnly, final SessionImplementor session, final PreLoadEvent preLoadEvent, final PostLoadEvent postLoadEvent) throws HibernateException { // TODO: Should this be an InitializeEntityEventListener??? (watch out for performance!) final PersistenceContext persistenceContext = session.getPersistenceContext(); EntityEntry entityEntry = persistenceContext.getEntry(entity); if (entityEntry == null) { throw new AssertionFailure("possible non-threadsafe access to the session"); } EntityPersister persister = entityEntry.getPersister(); Serializable id = entityEntry.getId(); Object[] hydratedState = entityEntry.getLoadedState(); if (log.isDebugEnabled()) log.debug( "resolving associations for " + MessageHelper.infoString(persister, id, session.getFactory())); Type[] types = persister.getPropertyTypes(); for (int i = 0; i < hydratedState.length; i++) { final Object value = hydratedState[i]; if (value != LazyPropertyInitializer.UNFETCHED_PROPERTY && value != BackrefPropertyAccessor.UNKNOWN) { hydratedState[i] = types[i].resolve(value, session, entity); } } // Must occur after resolving identifiers! if (session.isEventSource()) { preLoadEvent.setEntity(entity).setState(hydratedState).setId(id).setPersister(persister); PreLoadEventListener[] listeners = session.getListeners().getPreLoadEventListeners(); for (int i = 0; i < listeners.length; i++) { listeners[i].onPreLoad(preLoadEvent); } } persister.setPropertyValues(entity, hydratedState, session.getEntityMode()); final SessionFactoryImplementor factory = session.getFactory(); if (persister.hasCache() && session.getCacheMode().isPutEnabled()) { if (log.isDebugEnabled()) log.debug( "adding entity to second-level cache: " + MessageHelper.infoString(persister, id, session.getFactory())); Object version = Versioning.getVersion(hydratedState, persister); CacheEntry entry = new CacheEntry( hydratedState, persister, entityEntry.isLoadedWithLazyPropertiesUnfetched(), version, session, entity); CacheKey cacheKey = new CacheKey( id, persister.getIdentifierType(), persister.getRootEntityName(), session.getEntityMode(), session.getFactory()); boolean put = persister .getCache() .put( cacheKey, persister.getCacheEntryStructure().structure(entry), session.getTimestamp(), version, persister.isVersioned() ? persister.getVersionType().getComparator() : null, useMinimalPuts( session, entityEntry)); // we could use persister.hasLazyProperties() instead of true if (put && factory.getStatistics().isStatisticsEnabled()) { factory .getStatisticsImplementor() .secondLevelCachePut(persister.getCache().getRegionName()); } } if (readOnly || !persister.isMutable()) { // no need to take a snapshot - this is a // performance optimization, but not really // important, except for entities with huge // mutable property values persistenceContext.setEntryStatus(entityEntry, Status.READ_ONLY); } else { // take a snapshot TypeFactory.deepCopy( hydratedState, persister.getPropertyTypes(), persister.getPropertyUpdateability(), hydratedState, // after setting values to object, entityMode session); persistenceContext.setEntryStatus(entityEntry, Status.MANAGED); } persister.afterInitialize(entity, entityEntry.isLoadedWithLazyPropertiesUnfetched(), session); if (session.isEventSource()) { postLoadEvent.setEntity(entity).setId(id).setPersister(persister); PostLoadEventListener[] listeners = session.getListeners().getPostLoadEventListeners(); for (int i = 0; i < listeners.length; i++) { listeners[i].onPostLoad(postLoadEvent); } } if (log.isDebugEnabled()) log.debug( "done materializing entity " + MessageHelper.infoString(persister, id, session.getFactory())); if (factory.getStatistics().isStatisticsEnabled()) { factory.getStatisticsImplementor().loadEntity(persister.getEntityName()); } }