I’m in the process of migrating an app from JBoss 5.1.0, using hibernate3 to WildFly13, using hibernate5.
One of the last tasks I’m having to do is to rewrite a LoadEventListener so that it uses hibernate5 classes.
There are a few places in the code where I could not find an equivalent in hibernate5:
persister.getCache().lock(ck, null);
persister.getCache().release(ck, lock);
where persister is an EntityPersister,
Object values = entry.assemble(result, id, subclassPersister, session.getInterceptor(), session);
entry is missing the assemble method, where entry is a org.hibernate.cache.spi.entry.CacheEntry
TypeFactory.deepCopy(values, types, subclassPersister.getPropertyUpdateability(), values, session);
TypeFactory does not have the deepCopy method,
PostLoadEventListener listeners = session.getListeners().getPostLoadEventListeners();
and session is lacking the getListeners() method.
The entire class is pasted below, maybe someone can help me adapt the code to hibernate5 specs.
Thank you.
package com.hibernate.persistence;
import java.io.Serializable;
import org.apache.log4j.Logger;
import org.hibernate.HibernateException;
import org.hibernate.LockMode;
import org.hibernate.NonUniqueObjectException;
import org.hibernate.PersistentObjectException;
import org.hibernate.TypeMismatchException;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.cache.spi.access.EntityDataAccess;
import org.hibernate.cache.spi.entry.CacheEntry;
import org.hibernate.engine.internal.TwoPhaseLoad;
import org.hibernate.engine.internal.Versioning;
import org.hibernate.engine.spi.EntityEntry;
import org.hibernate.engine.spi.EntityKey;
import org.hibernate.engine.spi.PersistenceContext;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.engine.spi.Status;
import org.hibernate.event.internal.AbstractLockUpgradeEventListener;
import org.hibernate.event.spi.EventSource;
import org.hibernate.event.spi.LoadEvent;
import org.hibernate.event.spi.LoadEventListener;
import org.hibernate.event.spi.PostLoadEvent;
import org.hibernate.event.spi.PostLoadEventListener;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.pretty.MessageHelper;
import org.hibernate.proxy.HibernateProxy;
import org.hibernate.proxy.LazyInitializer;
import org.hibernate.type.Type;
import org.hibernate.type.TypeFactory;
public class LoadEventListener
extends
AbstractLockUpgradeEventListener
implements
org.hibernate.event.spi.LoadEventListener {
private static final long serialVersionUID = 1L;
public static final Object REMOVED_ENTITY_MARKER = new Object();
public static final Object INCONSISTENT_RTN_CLASS_MARKER = new Object();
public static final LockMode DEFAULT_LOCK_MODE = LockMode.NONE;
private static final Logger LOGGER = Logger.getLogger(LoadEventListener.class);
@Override
public void onLoad(final LoadEvent event, final LoadEventListener.LoadType loadType)
throws HibernateException {
final SessionImplementor source = event.getSession();
EntityPersister persister;
if (event.getInstanceToLoad() != null) {
persister = source.getEntityPersister(null, event.getInstanceToLoad());
event.setEntityClassName(event.getInstanceToLoad().getClass().getName());
} else {
persister = source.getFactory().getEntityPersister(event.getEntityClassName());
}
if (persister == null) {
throw new HibernateException("Unable to locate persister: " + event.getEntityClassName());
}
Class idClass = persister.getIdentifierType().getReturnedClass();
if (idClass != null && !idClass.isInstance(event.getEntityId())) {
throw new TypeMismatchException("Provided id of the wrong type. Expected: " + idClass + ", got " + event.getEntityId().getClass());
}
EntityKey keyToLoad = new EntityKey(event.getEntityId(), persister);
try {
if (loadType.isNakedEntityReturned()) {
event.setResult(this.load(event, persister, keyToLoad, loadType));
} else {
if (event.getLockMode() == LockMode.NONE) {
event.setResult(this.proxyOrLoad(event, persister, keyToLoad, loadType));
} else {
event.setResult(this.lockAndLoad(event, persister, keyToLoad, loadType, source));
}
}
} catch (HibernateException e) {
LoadEventListener.LOGGER.info("Error performing load command", e);
throw e;
}
}
protected Object load(final LoadEvent event, final EntityPersister persister, final EntityKey keyToLoad, final LoadEventListener.LoadType options)
throws HibernateException {
if (event.getInstanceToLoad() != null) {
if (event.getSession().getPersistenceContext().getEntry(event.getInstanceToLoad()) != null) {
throw new PersistentObjectException("attempted to load into an instance that was already associated with the session: "
+ MessageHelper.infoString(persister, event.getEntityId(), event.getSession().getFactory()));
}
persister.setIdentifier(event.getInstanceToLoad(), event.getEntityId(), event.getSession());
}
Object entity = this.doLoad(event, persister, keyToLoad, options);
boolean isOptionalInstance = event.getInstanceToLoad() != null;
if (!options.isAllowNulls() || isOptionalInstance) {
if (entity == null) {
event.getSession().getFactory().getEntityNotFoundDelegate().handleEntityNotFound(event.getEntityClassName(), event.getEntityId());
}
}
if (isOptionalInstance && entity != event.getInstanceToLoad()) {
throw new NonUniqueObjectException(event.getEntityId(), event.getEntityClassName());
}
return entity;
}
protected Object proxyOrLoad(final LoadEvent event, final EntityPersister persister, final EntityKey keyToLoad,
final LoadEventListener.LoadType options)
throws HibernateException {
if (LoadEventListener.LOGGER.isDebugEnabled()) {
LoadEventListener.LOGGER
.debug("loading entity: " + MessageHelper.infoString(persister, event.getEntityId(), event.getSession().getFactory()));
}
if (!persister.hasProxy()) {
return this.load(event, persister, keyToLoad, options);
} else {
final PersistenceContext persistenceContext = event.getSession().getPersistenceContext();
Object proxy = persistenceContext.getProxy(keyToLoad);
if (proxy != null) {
return this.returnNarrowedProxy(event, persister, keyToLoad, options, persistenceContext, proxy);
} else {
if (options.isAllowProxyCreation()) {
return this.createProxyIfNecessary(event, persister, keyToLoad, options, persistenceContext);
} else {
return this.load(event, persister, keyToLoad, options);
}
}
}
}
private Object returnNarrowedProxy(final LoadEvent event, final EntityPersister persister, final EntityKey keyToLoad,
final LoadEventListener.LoadType options, final PersistenceContext persistenceContext, final Object proxy) {
LoadEventListener.LOGGER.debug("entity proxy found in session cache");
LazyInitializer li = ((HibernateProxy)proxy).getHibernateLazyInitializer();
if (li.isUnwrap()) {
return li.getImplementation();
}
Object impl = null;
if (!options.isAllowProxyCreation()) {
impl = this.load(event, persister, keyToLoad, options);
if (impl == null) {
event.getSession().getFactory().getEntityNotFoundDelegate().handleEntityNotFound(persister.getEntityName(),
keyToLoad.getIdentifier());
}
}
return persistenceContext.narrowProxy(proxy, persister, keyToLoad, impl);
}
private Object createProxyIfNecessary(final LoadEvent event, final EntityPersister persister, final EntityKey keyToLoad,
final LoadEventListener.LoadType options, final PersistenceContext persistenceContext) {
Object existing = persistenceContext.getEntity(keyToLoad);
if (existing != null) {
LoadEventListener.LOGGER.debug("entity found in session cache");
if (options.isCheckDeleted()) {
EntityEntry entry = persistenceContext.getEntry(existing);
Status status = entry.getStatus();
if (status == Status.DELETED || status == Status.GONE) {
return null;
}
}
return existing;
} else {
LoadEventListener.LOGGER.debug("creating new proxy for entity");
Object proxy = persister.createProxy(event.getEntityId(), event.getSession());
persistenceContext.getBatchFetchQueue().addBatchLoadableEntityKey(keyToLoad);
persistenceContext.addProxy(keyToLoad, proxy);
return proxy;
}
}
protected Object lockAndLoad(final LoadEvent event, final EntityPersister persister, final EntityKey keyToLoad,
final LoadEventListener.LoadType options, final SessionImplementor source)
throws HibernateException {
CacheConcurrencyStrategy lock = null;
final EntityDataAccess cache = persister.getCacheAccessStrategy();
final Object ck = null;
if (persister.hasCache()) {
ck = cache.generateCacheKey(event.getEntityId(), persister, source.getFactory(), source.getTenantIdentifier());
lock = persister.getCache().lock(ck, null);
} else {
ck = null;
}
Object entity;
try {
entity = this.load(event, persister, keyToLoad, options);
} finally {
if (persister.hasCache()) {
persister.getCache().release(ck, lock);
}
}
Object proxy = event.getSession().getPersistenceContext().proxyFor(persister, keyToLoad, entity);
return proxy;
}
protected Object doLoad(final LoadEvent event, final EntityPersister persister, final EntityKey keyToLoad,
final LoadEventListener.LoadType options)
throws HibernateException {
if (LoadEventListener.LOGGER.isDebugEnabled()) {
LoadEventListener.LOGGER
.debug("attempting to resolve: " + MessageHelper.infoString(persister, event.getEntityId(), event.getSession().getFactory()));
}
Object entity = this.loadFromSessionCache(event, keyToLoad, options);
if (entity == LoadEventListener.REMOVED_ENTITY_MARKER) {
LoadEventListener.LOGGER.debug("load request found matching entity in context, but it is scheduled for removal; returning null");
return null;
}
if (entity == LoadEventListener.INCONSISTENT_RTN_CLASS_MARKER) {
LoadEventListener.LOGGER
.debug("load request found matching entity in context, but the matched entity was of an inconsistent return type; returning null");
return null;
}
if (entity != null) {
if (LoadEventListener.LOGGER.isDebugEnabled()) {
LoadEventListener.LOGGER.debug(
"resolved object in session cache: " + MessageHelper.infoString(persister, event.getEntityId(), event.getSession().getFactory()));
}
return entity;
}
entity = this.loadFromSecondLevelCache(event, persister, options);
if (entity != null) {
if (LoadEventListener.LOGGER.isDebugEnabled()) {
LoadEventListener.LOGGER.debug("resolved object in second-level cache: "
+ MessageHelper.infoString(persister, event.getEntityId(), event.getSession().getFactory()));
}
return entity;
}
if (LoadEventListener.LOGGER.isDebugEnabled()) {
LoadEventListener.LOGGER.debug(
"object not resolved in any cache: " + MessageHelper.infoString(persister, event.getEntityId(), event.getSession().getFactory()));
}
return this.loadFromDatasource(event, persister, keyToLoad, options);
}
protected Object loadFromDatasource(final LoadEvent event, final EntityPersister persister, final EntityKey keyToLoad,
final LoadEventListener.LoadType options)
throws HibernateException {
final SessionImplementor source = event.getSession();
Object entity = persister.load(event.getEntityId(), event.getInstanceToLoad(), event.getLockMode(), source);
if (event.isAssociationFetch() && source.getFactory().getStatistics().isStatisticsEnabled()) {
source.getFactory().getStatisticsImplementor().fetchEntity(event.getEntityClassName());
}
return entity;
}
protected Object loadFromSessionCache(final LoadEvent event, final EntityKey keyToLoad, final LoadEventListener.LoadType options)
throws HibernateException {
SessionImplementor session = event.getSession();
Object old = session.getEntityUsingInterceptor(keyToLoad);
if (old != null) {
EntityEntry oldEntry = session.getPersistenceContext().getEntry(old);
if (options.isCheckDeleted()) {
Status status = oldEntry.getStatus();
if (status == Status.DELETED || status == Status.GONE) {
return LoadEventListener.REMOVED_ENTITY_MARKER;
}
}
if (options.isAllowNulls()) {
EntityPersister persister = event.getSession().getFactory().getEntityPersister(event.getEntityClassName());
if (!persister.isInstance(old)) {
return LoadEventListener.INCONSISTENT_RTN_CLASS_MARKER;
}
}
this.upgradeLock(old, oldEntry, event.getLockOptions(), event.getSession());
}
return old;
}
protected Object loadFromSecondLevelCache(final LoadEvent event, final EntityPersister persister, final LoadEventListener.LoadType options)
throws HibernateException {
final SessionImplementor source = event.getSession();
final boolean useCache = persister.hasCache() && source.getCacheMode().isGetEnabled() && event.getLockMode().lessThan(LockMode.READ);
if (useCache) {
final SessionFactoryImplementor factory = source.getFactory();
final EntityDataAccess cache = persister.getCacheAccessStrategy();
final Object ck = cache.generateCacheKey(event.getEntityId(), persister, source.getFactory(), source.getTenantIdentifier());
Object ce = persister.getCache().get(ck, source.getTimestamp());
if (factory.getStatistics().isStatisticsEnabled()) {
if (ce == null) {
factory.getStatisticsImplementor().secondLevelCacheMiss(persister.getCache().getRegionName());
} else {
factory.getStatisticsImplementor().secondLevelCacheHit(persister.getCache().getRegionName());
}
}
if (ce != null) {
CacheEntry entry = (CacheEntry)persister.getCacheEntryStructure().destructure(ce, factory);
return this.assembleCacheEntry(entry, event.getEntityId(), persister, event);
}
}
return null;
}
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 (LoadEventListener.LOGGER.isDebugEnabled()) {
LoadEventListener.LOGGER.debug("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;
TwoPhaseLoad.addUninitializedCachedEntity(new EntityKey(id, subclassPersister), result, subclassPersister, LockMode.NONE, entry.getVersion(),
session);
Type[] types = subclassPersister.getPropertyTypes();
Object[] values = entry.assemble(result, id, subclassPersister, session.getInterceptor(), session);
TypeFactory.deepCopy(values, types, subclassPersister.getPropertyUpdateability(), values, session);
Object version = Versioning.getVersion(values, subclassPersister);
if (LoadEventListener.LOGGER.isDebugEnabled()) {
LoadEventListener.LOGGER.debug("Cached Version: " + version);
}
final PersistenceContext persistenceContext = session.getPersistenceContext();
persistenceContext.addEntry(result, Status.MANAGED, values, null, id, version, LockMode.NONE, true, subclassPersister, false);
subclassPersister.afterInitialize(result, session);
persistenceContext.initializeNonLazyCollections();
PostLoadEvent postLoadEvent = new PostLoadEvent(session).setEntity(result).setId(id).setPersister(persister);
PostLoadEventListener[] listeners = session.getListeners().getPostLoadEventListeners();
for (PostLoadEventListener listener : listeners) {
listener.onPostLoad(postLoadEvent);
}
return result;
}
}