|
We have a custom built cache and a CustomHibernateLayer. CustomeHibernateLayer is a thin layer which calls cache-methods like beforeGet, afterGet, beforePut, afterPut around Hibernate calls. These methods are called as:
beforeGet(); // returns entity from cache if its present here entityManager.find(...) afterGet(); Similarly for put, calls are:
beforePut(); entityManager.save(...) afterPut(); // puts entity into cache
Clients also use @PostLoad, @PreLoad, @PreLoad, @EntityListeners etc annotations on the entity objects.
Problem is with getting a cache-hit in beforeGet(). If there is a cache-hit, the @PostLoad methods and @EntityListeners methods are not called because hibernate's entityManager.find(...) is not called. Is there a way to force hibernate call @PostLoad methods?
Hibernate must be following a sequence like:
entity = callGetFromDB(); if (entity != null) runPostLoadHandlers (entity); So, I want to know if there is a method like runPostLoadHandlers() as mentioned in the above pseudo-code. If there is no such method, then clients may have to completely re-invent the wheel by reading annotations etc.
Here is a stack-trace for Hibernate code calling post-load handlers by default. This clearly shows that I should be able to call EJB3PostLoadEventListener.onPostLoad() to fulfill the cache-hit case.
at java.lang.reflect.Method.invoke(Method.java:597) at org.hibernate.ejb.event.ListenerCallback.invoke(ListenerCallback.java:48) at org.hibernate.ejb.event.EntityCallbackHandler.callback(EntityCallbackHandler.java:110) at org.hibernate.ejb.event.EntityCallbackHandler.postLoad(EntityCallbackHandler.java:103) at org.hibernate.ejb.event.EJB3PostLoadEventListener.onPostLoad(EJB3PostLoadEventListener.java:49) at org.hibernate.engine.internal.TwoPhaseLoad.doInitializeEntity(TwoPhaseLoad.java:292) at org.hibernate.engine.internal.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:134) at org.hibernate.loader.Loader.initializeEntitiesAndCollections(Loader.java:999) at org.hibernate.loader.Loader.doQuery(Loader.java:878) at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:293) at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:263) at org.hibernate.loader.Loader.loadEntity(Loader.java:1977) at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:82) at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:72) at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:3821) at org.hibernate.event.internal.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:458) at org.hibernate.event.internal.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:427) at org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEventListener.java:204) at org.hibernate.event.internal.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:260) at org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:148) at org.hibernate.internal.SessionImpl.fireLoad(SessionImpl.java:1075) at org.hibernate.internal.SessionImpl.access$2000(SessionImpl.java:175) at org.hibernate.internal.SessionImpl$IdentifierLoadAccessImpl.load(SessionImpl.java:2421) at org.hibernate.internal.SessionImpl.get(SessionImpl.java:975) at org.hibernate.event.internal.DefaultMergeEventListener.entityIsDetached(DefaultMergeEventListener.java:271) at org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:151) at org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:76) at org.hibernate.internal.SessionImpl.fireMerge(SessionImpl.java:900) at org.hibernate.internal.SessionImpl.merge(SessionImpl.java:884) at org.hibernate.internal.SessionImpl.merge(SessionImpl.java:888) at org.hibernate.ejb.AbstractEntityManagerImpl.merge(AbstractEntityManagerImpl.java:879)
I tried the below code, but it fails by a NullPointerException.
SessionImpl session = (SessionImpl) em.getDelegate(); PostLoadEvent postLoadEvent = null; if (session.isEventSource()) { postLoadEvent = new PostLoadEvent(session); }
final EventListenerGroup<PostLoadEventListener> listenerGroup = session .getFactory() .getServiceRegistry() .getService(EventListenerRegistry.class) .getEventListenerGroup(EventType.POST_LOAD); for (PostLoadEventListener listener : listenerGroup.listeners()) { listener.onPostLoad(postLoadEvent); }
|