diff --git a/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultMergeEventListener.java b/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultMergeEventListener.java index 046fdcff7af0..170479eb7641 100644 --- a/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultMergeEventListener.java +++ b/hibernate-core/src/main/java/org/hibernate/event/internal/DefaultMergeEventListener.java @@ -54,6 +54,7 @@ import static org.hibernate.engine.internal.ManagedTypeHelper.isPersistentAttributeInterceptable; import static org.hibernate.engine.internal.ManagedTypeHelper.isSelfDirtinessTracker; import static org.hibernate.event.internal.EntityState.getEntityState; +import static org.hibernate.event.internal.EventUtil.getLoggableName; import static org.hibernate.proxy.HibernateProxy.extractLazyInitializer; /** @@ -153,27 +154,21 @@ private void merge(MergeEvent event, MergeContext copiedAlready, Object entity) final EventSource source = event.getSession(); // Check the persistence context for an entry relating to this // entity to be merged... + final String entityName = event.getEntityName(); final PersistenceContext persistenceContext = source.getPersistenceContextInternal(); EntityEntry entry = persistenceContext.getEntry( entity ); final EntityState entityState; final Object copiedId; final Object originalId; if ( entry == null ) { - final EntityPersister persister = source.getEntityPersister( event.getEntityName(), entity ); + final EntityPersister persister = source.getEntityPersister( entityName, entity ); originalId = persister.getIdentifier( entity, copiedAlready ); if ( originalId != null ) { final EntityKey entityKey; - if ( persister.getIdentifierType() instanceof ComponentType ) { - /* - this is needed in case of composite id containing an association with a generated identifier, in such a case - generating the EntityKey will cause a NPE when trying to get the hashcode of the null id - */ - copiedId = copyCompositeTypeId( - originalId, - (ComponentType) persister.getIdentifierType(), - source, - copiedAlready - ); + if ( persister.getIdentifierType() instanceof ComponentType compositeId ) { + // this is needed in case of a composite id containing an association with a generated identifier + // in such a case, generating the EntityKey will cause NPE when evaluating the hashcode of the null id + copiedId = copyCompositeTypeId( originalId, compositeId, source, copiedAlready ); entityKey = source.generateEntityKey( copiedId, persister ); } else { @@ -191,18 +186,18 @@ private void merge(MergeEvent event, MergeContext copiedAlready, Object entity) entityState = EntityState.DETACHED; } else { - entityState = getEntityState( entity, event.getEntityName(), entry, source, false ); + entityState = getEntityState( entity, entityName, entry, source, false ); } } else { copiedId = null; - entityState = getEntityState( entity, event.getEntityName(), entry, source, false ); + entityState = getEntityState( entity, entityName, entry, source, false ); } } else { copiedId = null; originalId = null; - entityState = getEntityState( entity, event.getEntityName(), entry, source, false ); + entityState = getEntityState( entity, entityName, entry, source, false ); } switch ( entityState ) { @@ -217,22 +212,19 @@ private void merge(MergeEvent event, MergeContext copiedAlready, Object entity) break; default: //DELETED if ( persistenceContext.getEntry( entity ) == null ) { + final EntityPersister persister = source.getEntityPersister( entityName, entity ); assert persistenceContext.containsDeletedUnloadedEntityKey( source.generateEntityKey( - source.getEntityPersister( event.getEntityName(), entity ) - .getIdentifier( entity, event.getSession() ), - source.getEntityPersister( event.getEntityName(), entity ) + persister.getIdentifier( entity, event.getSession() ), + persister ) ); source.getActionQueue().unScheduleUnloadedDeletion( entity ); entityIsDetached(event, copiedId, originalId, copiedAlready); break; } - throw new ObjectDeletedException( - "deleted instance passed to merge", - null, - EventUtil.getLoggableName( event.getEntityName(), entity) - ); + throw new ObjectDeletedException( "deleted instance passed to merge", + originalId, getLoggableName( entityName, entity ) ); } } @@ -245,25 +237,33 @@ private static Object copyCompositeTypeId( final Object idCopy = compositeType.deepCopy( id, factory ); final Type[] subtypes = compositeType.getSubtypes(); final Object[] propertyValues = compositeType.getPropertyValues( id ); - final Object[] copyValues = compositeType.getPropertyValues( idCopy ); + final Object[] copiedValues = compositeType.getPropertyValues( idCopy ); for ( int i = 0; i < subtypes.length; i++ ) { - final Type subtype = subtypes[i]; - if ( subtype instanceof EntityType ) { - // the value of the copy in the MergeContext has the id assigned - final Object object = mergeContext.get( propertyValues[i] ); - copyValues[i] = object == null ? subtype.deepCopy( propertyValues[i], factory ) : object; - } - else if ( subtype instanceof AnyType anyType ) { - copyValues[i] = copyCompositeTypeId( propertyValues[i], anyType, session, mergeContext ); - } - else if ( subtype instanceof ComponentType componentType ) { - copyValues[i] = copyCompositeTypeId( propertyValues[i], componentType, session, mergeContext ); - } - else { - copyValues[i] = subtype.deepCopy( propertyValues[i], factory ); - } + copiedValues[i] = copy( session, mergeContext, subtypes[i], propertyValues[i], factory ); + } + return compositeType.replacePropertyValues( idCopy, copiedValues, session ); + } + + private static Object copy( + EventSource session, + MergeContext mergeContext, + Type subtype, + Object propertyValue, + SessionFactoryImplementor factory) { + if ( subtype instanceof EntityType ) { + // the value of the copy in the MergeContext has the id assigned + final Object object = mergeContext.get( propertyValue ); + return object == null ? subtype.deepCopy( propertyValue, factory ) : object; + } + else if ( subtype instanceof AnyType anyType ) { + return copyCompositeTypeId( propertyValue, anyType, session, mergeContext ); + } + else if ( subtype instanceof ComponentType componentType ) { + return copyCompositeTypeId( propertyValue, componentType, session, mergeContext ); + } + else { + return subtype.deepCopy( propertyValue, factory ); } - return compositeType.replacePropertyValues( idCopy, copyValues, session ); } protected void entityIsPersistent(MergeEvent event, MergeContext copyCache) {