5454import static org .hibernate .engine .internal .ManagedTypeHelper .isPersistentAttributeInterceptable ;
5555import static org .hibernate .engine .internal .ManagedTypeHelper .isSelfDirtinessTracker ;
5656import static org .hibernate .event .internal .EntityState .getEntityState ;
57+ import static org .hibernate .event .internal .EventUtil .getLoggableName ;
5758import static org .hibernate .proxy .HibernateProxy .extractLazyInitializer ;
5859
5960/**
@@ -153,27 +154,21 @@ private void merge(MergeEvent event, MergeContext copiedAlready, Object entity)
153154 final EventSource source = event .getSession ();
154155 // Check the persistence context for an entry relating to this
155156 // entity to be merged...
157+ final String entityName = event .getEntityName ();
156158 final PersistenceContext persistenceContext = source .getPersistenceContextInternal ();
157159 EntityEntry entry = persistenceContext .getEntry ( entity );
158160 final EntityState entityState ;
159161 final Object copiedId ;
160162 final Object originalId ;
161163 if ( entry == null ) {
162- final EntityPersister persister = source .getEntityPersister ( event . getEntityName () , entity );
164+ final EntityPersister persister = source .getEntityPersister ( entityName , entity );
163165 originalId = persister .getIdentifier ( entity , copiedAlready );
164166 if ( originalId != null ) {
165167 final EntityKey entityKey ;
166- if ( persister .getIdentifierType () instanceof ComponentType ) {
167- /*
168- this is needed in case of composite id containing an association with a generated identifier, in such a case
169- generating the EntityKey will cause a NPE when trying to get the hashcode of the null id
170- */
171- copiedId = copyCompositeTypeId (
172- originalId ,
173- (ComponentType ) persister .getIdentifierType (),
174- source ,
175- copiedAlready
176- );
168+ if ( persister .getIdentifierType () instanceof ComponentType compositeId ) {
169+ // this is needed in case of a composite id containing an association with a generated identifier
170+ // in such a case, generating the EntityKey will cause NPE when evaluating the hashcode of the null id
171+ copiedId = copyCompositeTypeId ( originalId , compositeId , source , copiedAlready );
177172 entityKey = source .generateEntityKey ( copiedId , persister );
178173 }
179174 else {
@@ -191,18 +186,18 @@ private void merge(MergeEvent event, MergeContext copiedAlready, Object entity)
191186 entityState = EntityState .DETACHED ;
192187 }
193188 else {
194- entityState = getEntityState ( entity , event . getEntityName () , entry , source , false );
189+ entityState = getEntityState ( entity , entityName , entry , source , false );
195190 }
196191 }
197192 else {
198193 copiedId = null ;
199- entityState = getEntityState ( entity , event . getEntityName () , entry , source , false );
194+ entityState = getEntityState ( entity , entityName , entry , source , false );
200195 }
201196 }
202197 else {
203198 copiedId = null ;
204199 originalId = null ;
205- entityState = getEntityState ( entity , event . getEntityName () , entry , source , false );
200+ entityState = getEntityState ( entity , entityName , entry , source , false );
206201 }
207202
208203 switch ( entityState ) {
@@ -217,22 +212,19 @@ private void merge(MergeEvent event, MergeContext copiedAlready, Object entity)
217212 break ;
218213 default : //DELETED
219214 if ( persistenceContext .getEntry ( entity ) == null ) {
215+ final EntityPersister persister = source .getEntityPersister ( entityName , entity );
220216 assert persistenceContext .containsDeletedUnloadedEntityKey (
221217 source .generateEntityKey (
222- source .getEntityPersister ( event .getEntityName (), entity )
223- .getIdentifier ( entity , event .getSession () ),
224- source .getEntityPersister ( event .getEntityName (), entity )
218+ persister .getIdentifier ( entity , event .getSession () ),
219+ persister
225220 )
226221 );
227222 source .getActionQueue ().unScheduleUnloadedDeletion ( entity );
228223 entityIsDetached (event , copiedId , originalId , copiedAlready );
229224 break ;
230225 }
231- throw new ObjectDeletedException (
232- "deleted instance passed to merge" ,
233- null ,
234- EventUtil .getLoggableName ( event .getEntityName (), entity )
235- );
226+ throw new ObjectDeletedException ( "deleted instance passed to merge" ,
227+ originalId , getLoggableName ( entityName , entity ) );
236228 }
237229 }
238230
@@ -245,25 +237,33 @@ private static Object copyCompositeTypeId(
245237 final Object idCopy = compositeType .deepCopy ( id , factory );
246238 final Type [] subtypes = compositeType .getSubtypes ();
247239 final Object [] propertyValues = compositeType .getPropertyValues ( id );
248- final Object [] copyValues = compositeType .getPropertyValues ( idCopy );
240+ final Object [] copiedValues = compositeType .getPropertyValues ( idCopy );
249241 for ( int i = 0 ; i < subtypes .length ; i ++ ) {
250- final Type subtype = subtypes [i ];
251- if ( subtype instanceof EntityType ) {
252- // the value of the copy in the MergeContext has the id assigned
253- final Object object = mergeContext .get ( propertyValues [i ] );
254- copyValues [i ] = object == null ? subtype .deepCopy ( propertyValues [i ], factory ) : object ;
255- }
256- else if ( subtype instanceof AnyType anyType ) {
257- copyValues [i ] = copyCompositeTypeId ( propertyValues [i ], anyType , session , mergeContext );
258- }
259- else if ( subtype instanceof ComponentType componentType ) {
260- copyValues [i ] = copyCompositeTypeId ( propertyValues [i ], componentType , session , mergeContext );
261- }
262- else {
263- copyValues [i ] = subtype .deepCopy ( propertyValues [i ], factory );
264- }
242+ copiedValues [i ] = copy ( session , mergeContext , subtypes [i ], propertyValues [i ], factory );
243+ }
244+ return compositeType .replacePropertyValues ( idCopy , copiedValues , session );
245+ }
246+
247+ private static Object copy (
248+ EventSource session ,
249+ MergeContext mergeContext ,
250+ Type subtype ,
251+ Object propertyValue ,
252+ SessionFactoryImplementor factory ) {
253+ if ( subtype instanceof EntityType ) {
254+ // the value of the copy in the MergeContext has the id assigned
255+ final Object object = mergeContext .get ( propertyValue );
256+ return object == null ? subtype .deepCopy ( propertyValue , factory ) : object ;
257+ }
258+ else if ( subtype instanceof AnyType anyType ) {
259+ return copyCompositeTypeId ( propertyValue , anyType , session , mergeContext );
260+ }
261+ else if ( subtype instanceof ComponentType componentType ) {
262+ return copyCompositeTypeId ( propertyValue , componentType , session , mergeContext );
263+ }
264+ else {
265+ return subtype .deepCopy ( propertyValue , factory );
265266 }
266- return compositeType .replacePropertyValues ( idCopy , copyValues , session );
267267 }
268268
269269 protected void entityIsPersistent (MergeEvent event , MergeContext copyCache ) {
0 commit comments