Skip to content

Commit b4aae92

Browse files
Jaanus Hansendreab8
authored andcommitted
HHH-4815 Implement support for orphan removal of assocations within embeddables
1 parent 70785ba commit b4aae92

File tree

3 files changed

+223
-34
lines changed

3 files changed

+223
-34
lines changed

hibernate-core/src/main/java/org/hibernate/engine/internal/Cascade.java

Lines changed: 39 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@
77
package org.hibernate.engine.internal;
88

99
import java.io.Serializable;
10+
import java.util.ArrayList;
1011
import java.util.Collection;
1112
import java.util.HashSet;
1213
import java.util.Iterator;
14+
import java.util.List;
1315

1416
import org.hibernate.HibernateException;
1517
import org.hibernate.bytecode.enhance.spi.interceptor.LazyAttributeLoadingInterceptor;
@@ -29,6 +31,7 @@
2931
import org.hibernate.proxy.HibernateProxy;
3032
import org.hibernate.type.AssociationType;
3133
import org.hibernate.type.CollectionType;
34+
import org.hibernate.type.ComponentType;
3235
import org.hibernate.type.CompositeType;
3336
import org.hibernate.type.EntityType;
3437
import org.hibernate.type.ForeignKeyDirection;
@@ -90,7 +93,6 @@ public static void cascade(
9093
final String[] propertyNames = persister.getPropertyNames();
9194
final CascadeStyle[] cascadeStyles = persister.getPropertyCascadeStyles();
9295
final boolean hasUninitializedLazyProperties = persister.hasUninitializedLazyProperties( parent );
93-
final int componentPathStackDepth = 0;
9496
for ( int i = 0; i < types.length; i++) {
9597
final CascadeStyle style = cascadeStyles[ i ];
9698
final String propertyName = propertyNames[ i ];
@@ -152,7 +154,7 @@ else if ( action.performOnLazyProperty() && types[ i ].isEntityType() ) {
152154
action,
153155
cascadePoint,
154156
eventSource,
155-
componentPathStackDepth,
157+
null,
156158
parent,
157159
child,
158160
types[ i ],
@@ -177,7 +179,7 @@ else if ( action.performOnLazyProperty() && types[ i ].isEntityType() ) {
177179
cascadeLogicalOneToOneOrphanRemoval(
178180
action,
179181
eventSource,
180-
componentPathStackDepth,
182+
null,
181183
parent,
182184
persister.getPropertyValue( parent, i ),
183185
types[ i ],
@@ -202,7 +204,7 @@ private static void cascadeProperty(
202204
final CascadingAction action,
203205
final CascadePoint cascadePoint,
204206
final EventSource eventSource,
205-
final int componentPathStackDepth,
207+
List<String> componentPath,
206208
final Object parent,
207209
final Object child,
208210
final Type type,
@@ -219,7 +221,7 @@ private static void cascadeProperty(
219221
action,
220222
cascadePoint,
221223
eventSource,
222-
componentPathStackDepth,
224+
componentPath,
223225
parent,
224226
child,
225227
type,
@@ -230,23 +232,28 @@ private static void cascadeProperty(
230232
}
231233
}
232234
else if ( type.isComponentType() ) {
235+
if ( componentPath == null ) {
236+
componentPath = new ArrayList<>();
237+
}
238+
componentPath.add( propertyName );
233239
cascadeComponent(
234240
action,
235241
cascadePoint,
236242
eventSource,
237-
componentPathStackDepth,
243+
componentPath,
238244
parent,
239245
child,
240246
(CompositeType) type,
241247
anything
242248
);
249+
componentPath.remove( componentPath.size() - 1 );
243250
}
244251
}
245252

246253
cascadeLogicalOneToOneOrphanRemoval(
247254
action,
248255
eventSource,
249-
componentPathStackDepth,
256+
componentPath,
250257
parent,
251258
child,
252259
type,
@@ -258,7 +265,7 @@ else if ( type.isComponentType() ) {
258265
private static void cascadeLogicalOneToOneOrphanRemoval(
259266
final CascadingAction action,
260267
final EventSource eventSource,
261-
final int componentPathStackDepth,
268+
final List<String> componentPath,
262269
final Object parent,
263270
final Object child,
264271
final Type type,
@@ -277,26 +284,26 @@ private static void cascadeLogicalOneToOneOrphanRemoval(
277284
final EntityEntry entry = persistenceContext.getEntry( parent );
278285
if ( entry != null && entry.getStatus() != Status.SAVING ) {
279286
Object loadedValue;
280-
if ( componentPathStackDepth == 0 ) {
287+
if ( componentPath == null ) {
281288
// association defined on entity
282289
loadedValue = entry.getLoadedValue( propertyName );
283290
}
284291
else {
285292
// association defined on component
286-
// todo : this is currently unsupported because of the fact that
287-
// we do not know the loaded state of this value properly
288-
// and doing so would be very difficult given how components and
289-
// entities are loaded (and how 'loaded state' is put into the
290-
// EntityEntry). Solutions here are to either:
291-
// 1) properly account for components as a 2-phase load construct
292-
// 2) just assume the association was just now orphaned and
293-
// issue the orphan delete. This would require a special
294-
// set of SQL statements though since we do not know the
295-
// orphaned value, something a delete with a subquery to
296-
// match the owner.
297-
// final EntityType entityType = (EntityType) type;
298-
// final String getPropertyPath = composePropertyPath( entityType.getPropertyName() );
299-
loadedValue = null;
293+
// Since the loadedState in the EntityEntry is a flat domain type array
294+
// We first have to extract the component object and then ask the component type
295+
// recursively to give us the value of the sub-property of that object
296+
loadedValue = entry.getLoadedValue( componentPath.get( 0 ) );
297+
ComponentType componentType = (ComponentType) entry.getPersister().getPropertyType( componentPath.get( 0 ) );
298+
if ( componentPath.size() != 1 ) {
299+
for ( int i = 1; i < componentPath.size(); i++ ) {
300+
final int subPropertyIndex = componentType.getPropertyIndex( componentPath.get( i ) );
301+
loadedValue = componentType.getPropertyValue( loadedValue, subPropertyIndex );
302+
componentType = (ComponentType) componentType.getSubtypes()[subPropertyIndex];
303+
}
304+
}
305+
306+
loadedValue = componentType.getPropertyValue( loadedValue, componentType.getPropertyIndex( propertyName ) );
300307
}
301308

302309
// orphaned if the association was nulled (child == null) or receives a new value while the
@@ -367,7 +374,7 @@ private static void cascadeComponent(
367374
final CascadingAction action,
368375
final CascadePoint cascadePoint,
369376
final EventSource eventSource,
370-
final int componentPathStackDepth,
377+
final List<String> componentPath,
371378
final Object parent,
372379
final Object child,
373380
final CompositeType componentType,
@@ -379,7 +386,7 @@ private static void cascadeComponent(
379386
for ( int i = 0; i < types.length; i++ ) {
380387
final CascadeStyle componentPropertyStyle = componentType.getCascadeStyle( i );
381388
final String subPropertyName = propertyNames[i];
382-
if ( componentPropertyStyle.doCascade( action ) ) {
389+
if ( componentPropertyStyle.doCascade( action ) || componentPropertyStyle.hasOrphanDelete() && action.deleteOrphans() ) {
383390
if (children == null) {
384391
// Get children on demand.
385392
children = componentType.getPropertyValues( child, eventSource );
@@ -388,7 +395,7 @@ private static void cascadeComponent(
388395
action,
389396
cascadePoint,
390397
eventSource,
391-
componentPathStackDepth + 1,
398+
componentPath,
392399
parent,
393400
children[i],
394401
types[i],
@@ -405,7 +412,7 @@ private static void cascadeAssociation(
405412
final CascadingAction action,
406413
final CascadePoint cascadePoint,
407414
final EventSource eventSource,
408-
final int componentPathStackDepth,
415+
final List<String> componentPath,
409416
final Object parent,
410417
final Object child,
411418
final Type type,
@@ -420,7 +427,7 @@ else if ( type.isCollectionType() ) {
420427
action,
421428
cascadePoint,
422429
eventSource,
423-
componentPathStackDepth,
430+
componentPath,
424431
parent,
425432
child,
426433
style,
@@ -437,7 +444,7 @@ private static void cascadeCollection(
437444
final CascadingAction action,
438445
final CascadePoint cascadePoint,
439446
final EventSource eventSource,
440-
final int componentPathStackDepth,
447+
final List<String> componentPath,
441448
final Object parent,
442449
final Object child,
443450
final CascadeStyle style,
@@ -457,7 +464,7 @@ private static void cascadeCollection(
457464
action,
458465
elementsCascadePoint,
459466
eventSource,
460-
componentPathStackDepth,
467+
componentPath,
461468
parent,
462469
child,
463470
type,
@@ -504,7 +511,7 @@ private static void cascadeCollectionElements(
504511
final CascadingAction action,
505512
final CascadePoint cascadePoint,
506513
final EventSource eventSource,
507-
final int componentPathStackDepth,
514+
final List<String> componentPath,
508515
final Object parent,
509516
final Object child,
510517
final CollectionType collectionType,
@@ -526,7 +533,7 @@ private static void cascadeCollectionElements(
526533
action,
527534
cascadePoint,
528535
eventSource,
529-
componentPathStackDepth,
536+
componentPath,
530537
parent,
531538
itr.next(),
532539
elemType,

0 commit comments

Comments
 (0)