HHH-11922 - Entity with null many-to-one cannot be loaded when associated entity has composite ID with hibernate.create_empty_composites.enabled=true

This commit is contained in:
Gail Badner 2017-08-15 21:53:29 -07:00
parent eafc5fe105
commit ef81e39d19
2 changed files with 34 additions and 3 deletions

View File

@ -860,7 +860,21 @@ public abstract class Loader {
}
}
}
final Serializable resolvedId = (Serializable) idType.resolve( hydratedKeyState[i], session, null );
// If hydratedKeyState[i] is null, then we know the association should be null.
// Don't bother resolving the ID if hydratedKeyState[i] is null.
// Implementation note: if the ID is a composite ID, then resolving a null value will
// result in instantiating an empty composite if AvailableSettings#CREATE_EMPTY_COMPOSITES_ENABLED
// is true. By not resolving a null value for a composite ID, we avoid the overhead of instantiating
// an empty composite, checking if it is equivalent to null (it should be), then ultimately throwing
// out the empty value.
final Serializable resolvedId;
if ( hydratedKeyState[i] != null ) {
resolvedId = (Serializable) idType.resolve( hydratedKeyState[i], session, null );
}
else {
resolvedId = null;
}
keys[i] = resolvedId == null ? null : session.generateEntityKey( resolvedId, persisters[i] );
}
}

View File

@ -175,8 +175,25 @@ public class ManyToOneType extends EntityType {
// return the (fully resolved) identifier value, but do not resolve
// to the actual referenced entity instance
// NOTE: the owner of the association is not really the owner of the id!
final Serializable id = (Serializable) getIdentifierOrUniqueKeyType( session.getFactory() )
.nullSafeGet( rs, names, session, null );
// First hydrate the ID to check if it is null.
// Don't bother resolving the ID if hydratedKeyState[i] is null.
// Implementation note: if id is a composite ID, then resolving a null value will
// result in instantiating an empty composite if AvailableSettings#CREATE_EMPTY_COMPOSITES_ENABLED
// is true. By not resolving a null value for a composite ID, we avoid the overhead of instantiating
// an empty composite, checking if it is equivalent to null (it should be), then ultimately throwing
// out the empty value.
final Object hydratedId = getIdentifierOrUniqueKeyType( session.getFactory() )
.hydrate( rs, names, session, null );
final Serializable id;
if ( hydratedId != null ) {
id = (Serializable) getIdentifierOrUniqueKeyType( session.getFactory() )
.resolve( hydratedId, session, null );
}
else {
id = null;
}
scheduleBatchLoadIfNeeded( id, session );
return id;
}