Faced the same issue.
It seems to me that the reason of the issue is the null check in
org.hibernate.event.def.DefaultLoadEventListener.javaCode:
private Object returnNarrowedProxy(
final LoadEvent event,
final EntityPersister persister,
final EntityKey keyToLoad,
final LoadEventListener.LoadType options,
final PersistenceContext persistenceContext,
final Object proxy) {
log.trace("entity proxy found in session cache");
LazyInitializer li = ( (HibernateProxy) proxy ).getHibernateLazyInitializer();
if ( li.isUnwrap() ) {
return li.getImplementation();
}
Object impl = null;
if ( !options.isAllowProxyCreation() ) {
impl = load( event, persister, keyToLoad, options );
if ( impl == null ) {
event.getSession().getFactory().getEntityNotFoundDelegate().handleEntityNotFound( persister.getEntityName(), keyToLoad.getIdentifier());
}
}
return persistenceContext.narrowProxy( proxy, persister, keyToLoad, impl );
}
Method
load( event, persister, keyToLoad, options ) checks returned proxy against null, but throws an exception only if null is not allowed
Quote:
protected Object load(
final LoadEvent event,
final EntityPersister persister,
final EntityKey keyToLoad,
final LoadEventListener.LoadType options) {
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 = 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;
}
But returnNarrowedProxy does not check it and if the second method returns null - throws an exception for both GET and LOAD