Ability to call postLoad handlers by clients

Description

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);
}

Activity

Show:

Christian Beikov January 21, 2025 at 3:33 PM

In ORM 6, post-load is called when it comes from the cache.

Out of Date

Details

Assignee

Reporter

Labels

Components

Priority

Created January 20, 2014 at 5:50 PM
Updated January 21, 2025 at 3:33 PM
Resolved January 21, 2025 at 3:33 PM