54
54
import static org .hibernate .engine .internal .ManagedTypeHelper .isPersistentAttributeInterceptable ;
55
55
import static org .hibernate .engine .internal .ManagedTypeHelper .isSelfDirtinessTracker ;
56
56
import static org .hibernate .event .internal .EntityState .getEntityState ;
57
+ import static org .hibernate .event .internal .EventUtil .getLoggableName ;
57
58
import static org .hibernate .proxy .HibernateProxy .extractLazyInitializer ;
58
59
59
60
/**
@@ -153,27 +154,21 @@ private void merge(MergeEvent event, MergeContext copiedAlready, Object entity)
153
154
final EventSource source = event .getSession ();
154
155
// Check the persistence context for an entry relating to this
155
156
// entity to be merged...
157
+ final String entityName = event .getEntityName ();
156
158
final PersistenceContext persistenceContext = source .getPersistenceContextInternal ();
157
159
EntityEntry entry = persistenceContext .getEntry ( entity );
158
160
final EntityState entityState ;
159
161
final Object copiedId ;
160
162
final Object originalId ;
161
163
if ( entry == null ) {
162
- final EntityPersister persister = source .getEntityPersister ( event . getEntityName () , entity );
164
+ final EntityPersister persister = source .getEntityPersister ( entityName , entity );
163
165
originalId = persister .getIdentifier ( entity , copiedAlready );
164
166
if ( originalId != null ) {
165
167
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 );
177
172
entityKey = source .generateEntityKey ( copiedId , persister );
178
173
}
179
174
else {
@@ -191,18 +186,18 @@ private void merge(MergeEvent event, MergeContext copiedAlready, Object entity)
191
186
entityState = EntityState .DETACHED ;
192
187
}
193
188
else {
194
- entityState = getEntityState ( entity , event . getEntityName () , entry , source , false );
189
+ entityState = getEntityState ( entity , entityName , entry , source , false );
195
190
}
196
191
}
197
192
else {
198
193
copiedId = null ;
199
- entityState = getEntityState ( entity , event . getEntityName () , entry , source , false );
194
+ entityState = getEntityState ( entity , entityName , entry , source , false );
200
195
}
201
196
}
202
197
else {
203
198
copiedId = null ;
204
199
originalId = null ;
205
- entityState = getEntityState ( entity , event . getEntityName () , entry , source , false );
200
+ entityState = getEntityState ( entity , entityName , entry , source , false );
206
201
}
207
202
208
203
switch ( entityState ) {
@@ -217,22 +212,19 @@ private void merge(MergeEvent event, MergeContext copiedAlready, Object entity)
217
212
break ;
218
213
default : //DELETED
219
214
if ( persistenceContext .getEntry ( entity ) == null ) {
215
+ final EntityPersister persister = source .getEntityPersister ( entityName , entity );
220
216
assert persistenceContext .containsDeletedUnloadedEntityKey (
221
217
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
225
220
)
226
221
);
227
222
source .getActionQueue ().unScheduleUnloadedDeletion ( entity );
228
223
entityIsDetached (event , copiedId , originalId , copiedAlready );
229
224
break ;
230
225
}
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 ) );
236
228
}
237
229
}
238
230
@@ -245,25 +237,33 @@ private static Object copyCompositeTypeId(
245
237
final Object idCopy = compositeType .deepCopy ( id , factory );
246
238
final Type [] subtypes = compositeType .getSubtypes ();
247
239
final Object [] propertyValues = compositeType .getPropertyValues ( id );
248
- final Object [] copyValues = compositeType .getPropertyValues ( idCopy );
240
+ final Object [] copiedValues = compositeType .getPropertyValues ( idCopy );
249
241
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 );
265
266
}
266
- return compositeType .replacePropertyValues ( idCopy , copyValues , session );
267
267
}
268
268
269
269
protected void entityIsPersistent (MergeEvent event , MergeContext copyCache ) {
0 commit comments