I’m currently working on the Hibernate migration to 5.3.x. I’ve just discovered that org.hibernate.event.internal.DefaultLoadEventListener#loadFromDatasource is now private instead of protected as I’ve hooked in here to solve some inheritance joining issues that come with our core design. Is there a specific reason why the visibility has been restricted?
It most likely is a simple refactor based on the fact that DefaultLoadEventListener is an internal class and we don’t expect users to override such a class in the way that you described typically.
Can you elaborate on your inheritance join issue so we can determine if there is a better approach?
Hi there,
sorry for the delay, I was sick the last week.
Basically we have a big “Base” table that a large number of classes inherit from, using joined inheritance. The Base table includes the database identifier and the qualified class name). When I simply want to query a Base entity by using the ID, I cannot do this on MySQL/MariaDB due to the 61 table join issue. This means that I always have to prequery the Base table to get the correct class by ID, then I can query the proper ID/class combination.
For a better understanding, I have attached the existing implementation I used in Hibernate 4.3, skipping some helper methods:
If you can help me with better approach (yes, I know that the design approach with inheritance was wrong in the first place, but we have to stick to this), I’d be very grateful.
I tried to implement an EntityPersister based approach, but effectively I don’t see where I have a mutable handle on the class being loaded as only id and session are effectively available and the EntityPersister itself already supplies the class.
This is what I tried in the first place (I decided to extend from JoinedSubclassEntityPersister). But I didn’t find any appropriate method to override without digging really deep in. For from my current point of view, overriding the load listener is the most straight-forward approach that requires the least amount of additional code:
@Override
public void onLoad(LoadEvent event, LoadType loadType) throws HibernateException {
String classToCheck = event.getEntityClassName();
if (preloadProperClassToPreventTableLimit(classToCheck)) {
// bypassing 61 table limit
String newClassName = lookupClass(event);
LOGGER.debug("Change {} to {} for ID {}", classToCheck, newClassName, event.getEntityId());
event.setEntityClassName(newClassName);
}
super.onLoad(event, loadType);
}
The previously mentioned approach has the serious performance drawback that the additional preload logic (that is triggering one lightweight DB query) is always executed, no matter if the entity is already on the cache or if it needs to be loaded from the datasource. This decision cannot be made in the onLoad method.
So basically the only solution I currently see to keep existing behaviour is
to use a custom implementation that is copied from DefaultLoadEventListener
and to change the persister based on the preloaded class directly before using loadFromDataSource
To avoid code duplication, it is critical that both loadFromDataSource is protected (and, even better, also getPersister().
Btw, it seems that DefaultLoadEventListener#getEvenListenerGroup and DefaultLoadEventListener#assembleCacheEntry is dead code.
Could you prepare a PR with what you exactly want? It will be easier for us to review and be sure the right thing is done.
We will release 5.3.1 very soon (it’s a matter of hours now) so if you can provide it quickly, it might help to get it in.
Keep in mind that we should definitely find a better solution for this issue as extending an internal class is not recommended to say the least but we can keep that for another day.