2020import org .hibernate .cache .spi .entry .ReferenceCacheEntryImpl ;
2121import org .hibernate .cache .spi .entry .StandardCacheEntryImpl ;
2222import org .hibernate .engine .internal .CacheHelper ;
23+ import org .hibernate .engine .internal .StatefulPersistenceContext ;
2324import org .hibernate .engine .internal .TwoPhaseLoad ;
2425import org .hibernate .engine .internal .Versioning ;
2526import org .hibernate .engine .spi .EntityEntry ;
2627import org .hibernate .engine .spi .EntityKey ;
28+ import org .hibernate .engine .spi .ManagedEntity ;
2729import org .hibernate .engine .spi .PersistenceContext ;
2830import org .hibernate .engine .spi .SessionFactoryImplementor ;
2931import org .hibernate .engine .spi .SessionImplementor ;
3032import org .hibernate .engine .spi .Status ;
33+ import org .hibernate .event .service .spi .EventListenerGroup ;
3134import org .hibernate .event .service .spi .EventListenerRegistry ;
3235import org .hibernate .event .spi .EventSource ;
3336import org .hibernate .event .spi .EventType ;
@@ -603,19 +606,101 @@ protected Object loadFromSecondLevelCache(
603606 }
604607
605608 CacheEntry entry = (CacheEntry ) persister .getCacheEntryStructure ().destructure ( ce , factory );
606- Object entity = convertCacheEntryToEntity ( entry , event .getEntityId (), persister , event , entityKey );
607-
609+ final Object entity ;
610+ if (entry .isReferenceEntry ()) {
611+ if ( event .getInstanceToLoad () != null ) {
612+ throw new HibernateException (
613+ String .format ( "Attempt to load entity [%s] from cache using provided object instance, but cache " +
614+ "is storing references: " + event .getEntityId ()));
615+ }
616+ else {
617+ entity = convertCacheReferenceEntryToEntity ( (ReferenceCacheEntryImpl ) entry ,
618+ event .getEntityId (), persister , event .getSession (), entityKey );
619+ }
620+ }
621+ else {
622+ entity = convertCacheEntryToEntity ( entry , event .getEntityId (), persister , event , entityKey );
623+ }
624+
608625 if ( !persister .isInstance ( entity ) ) {
609626 throw new WrongClassException (
610627 "loaded object was of wrong class " + entity .getClass (),
611628 event .getEntityId (),
612629 persister .getEntityName ()
613630 );
614631 }
615-
632+
616633 return entity ;
617634 }
618635
636+ private Object convertCacheReferenceEntryToEntity (
637+ ReferenceCacheEntryImpl referenceCacheEntry ,
638+ Serializable entityId ,
639+ EntityPersister persister ,
640+ EventSource session ,
641+ EntityKey entityKey ) {
642+ final Object entity = referenceCacheEntry .getReference ();
643+
644+ if ( entity == null ) {
645+ throw new IllegalStateException (
646+ "Reference cache entry contained null : " + entityId );
647+ }
648+ else {
649+ makeEntityCircularReferenceSafe (referenceCacheEntry , entityId , session , entity , entityKey );
650+ //PostLoad is needed for EJB3
651+ EventListenerGroup <PostLoadEventListener > evenListenerGroup = getEvenListenerGroup (session );
652+
653+ if (!evenListenerGroup .isEmpty ()) {
654+ postLoad (session , evenListenerGroup .listeners (), entity , entityId , persister );
655+ }
656+ return entity ;
657+ }
658+ }
659+
660+ private void postLoad (EventSource session , Iterable <PostLoadEventListener > listeners ,
661+ Object entity , Serializable entityId , EntityPersister persister ) {
662+ PostLoadEvent postLoadEvent = new PostLoadEvent (session )
663+ .setEntity (entity )
664+ .setId (entityId )
665+ .setPersister (persister );
666+
667+ for (PostLoadEventListener listener : listeners ) {
668+ listener .onPostLoad (postLoadEvent );
669+ }
670+ }
671+
672+ private void makeEntityCircularReferenceSafe (ReferenceCacheEntryImpl referenceCacheEntry ,
673+ Serializable entityId ,
674+ EventSource session ,
675+ Object entity ,
676+ EntityKey entityKey ) {
677+
678+ final EntityPersister subclassPersister = referenceCacheEntry .getSubclassPersister ();
679+ // make it circular-reference safe
680+ final StatefulPersistenceContext statefulPersistenceContext = (StatefulPersistenceContext ) session .getPersistenceContext ();
681+
682+ if ( (entity instanceof ManagedEntity ) ) {
683+ statefulPersistenceContext .addReferenceEntry (
684+ entity ,
685+ Status .READ_ONLY
686+ );
687+ }
688+ else {
689+ TwoPhaseLoad .addUninitializedCachedEntity (
690+ entityKey ,
691+ entity ,
692+ subclassPersister ,
693+ LockMode .NONE ,
694+ referenceCacheEntry .areLazyPropertiesUnfetched (),
695+ referenceCacheEntry .getVersion (),
696+ session
697+ );
698+ }
699+
700+ subclassPersister .afterInitialize ( entity , referenceCacheEntry .areLazyPropertiesUnfetched (), session );
701+ statefulPersistenceContext .initializeNonLazyCollections ();
702+ }
703+
619704 private Object convertCacheEntryToEntity (
620705 CacheEntry entry ,
621706 Serializable entityId ,
@@ -636,38 +721,12 @@ private Object convertCacheEntryToEntity(
636721 }
637722
638723 final Object entity ;
639- if ( entry .isReferenceEntry () ) {
640- final Object optionalObject = event .getInstanceToLoad ();
641- if ( optionalObject != null ) {
642- throw new HibernateException (
643- String .format (
644- "Attempt to load entity [%s] from cache using provided object instance, but cache " +
645- "is storing references" ,
646- MessageHelper .infoString ( persister , entityId , factory )
647- )
648- );
649- }
650724
651- ReferenceCacheEntryImpl referenceCacheEntry = (ReferenceCacheEntryImpl ) entry ;
652- entity = referenceCacheEntry .getReference ();
653- if ( entity == null ) {
654- throw new IllegalStateException (
655- "Reference cache entry contained null : " + MessageHelper .infoString (
656- persister ,
657- entityId ,
658- factory
659- )
660- );
661- }
662- subclassPersister = referenceCacheEntry .getSubclassPersister ();
663- }
664- else {
665- subclassPersister = factory .getEntityPersister ( entry .getSubclass () );
666- final Object optionalObject = event .getInstanceToLoad ();
667- entity = optionalObject == null
668- ? session .instantiate ( subclassPersister , entityId )
669- : optionalObject ;
670- }
725+ subclassPersister = factory .getEntityPersister ( entry .getSubclass () );
726+ final Object optionalObject = event .getInstanceToLoad ();
727+ entity = optionalObject == null
728+ ? session .instantiate ( subclassPersister , entityId )
729+ : optionalObject ;
671730
672731 // make it circular-reference safe
673732 TwoPhaseLoad .addUninitializedCachedEntity (
@@ -684,38 +743,32 @@ private Object convertCacheEntryToEntity(
684743 final Object [] values ;
685744 final Object version ;
686745 final boolean isReadOnly ;
687- if ( entry .isReferenceEntry () ) {
688- values = null ;
689- version = null ;
690- isReadOnly = true ;
691- }
692- else {
693- final Type [] types = subclassPersister .getPropertyTypes ();
694- // initializes the entity by (desired) side-effect
695- values = ( (StandardCacheEntryImpl ) entry ).assemble (
696- entity , entityId , subclassPersister , session .getInterceptor (), session
746+
747+ final Type [] types = subclassPersister .getPropertyTypes ();
748+ // initializes the entity by (desired) side-effect
749+ values = ( (StandardCacheEntryImpl ) entry ).assemble (
750+ entity , entityId , subclassPersister , session .getInterceptor (), session
751+ );
752+ if ( ( (StandardCacheEntryImpl ) entry ).isDeepCopyNeeded () ) {
753+ TypeHelper .deepCopy (
754+ values ,
755+ types ,
756+ subclassPersister .getPropertyUpdateability (),
757+ values ,
758+ session
697759 );
698- if ( ( (StandardCacheEntryImpl ) entry ).isDeepCopyNeeded () ) {
699- TypeHelper .deepCopy (
700- values ,
701- types ,
702- subclassPersister .getPropertyUpdateability (),
703- values ,
704- session
705- );
706- }
707- version = Versioning .getVersion ( values , subclassPersister );
708- LOG .tracef ( "Cached Version : %s" , version );
760+ }
761+ version = Versioning .getVersion ( values , subclassPersister );
762+ LOG .tracef ( "Cached Version : %s" , version );
709763
710- final Object proxy = persistenceContext .getProxy ( entityKey );
711- if ( proxy != null ) {
712- // there is already a proxy for this impl
713- // only set the status to read-only if the proxy is read-only
714- isReadOnly = ( (HibernateProxy ) proxy ).getHibernateLazyInitializer ().isReadOnly ();
715- }
716- else {
717- isReadOnly = session .isDefaultReadOnly ();
718- }
764+ final Object proxy = persistenceContext .getProxy ( entityKey );
765+ if ( proxy != null ) {
766+ // there is already a proxy for this impl
767+ // only set the status to read-only if the proxy is read-only
768+ isReadOnly = ( (HibernateProxy ) proxy ).getHibernateLazyInitializer ().isReadOnly ();
769+ }
770+ else {
771+ isReadOnly = session .isDefaultReadOnly ();
719772 }
720773
721774 persistenceContext .addEntry (
@@ -852,4 +905,14 @@ private Iterable<PostLoadEventListener> postLoadEventListeners(EventSource sessi
852905 .getEventListenerGroup ( EventType .POST_LOAD )
853906 .listeners ();
854907 }
908+
909+ private EventListenerGroup <PostLoadEventListener > getEvenListenerGroup (EventSource session ) {
910+ return session
911+ .getFactory ()
912+ .getServiceRegistry ()
913+ .getService ( EventListenerRegistry .class )
914+ .getEventListenerGroup ( EventType .POST_LOAD );
915+
916+ }
917+
855918}
0 commit comments