77package org .hibernate .engine .internal ;
88
99import java .io .Serializable ;
10+ import java .util .ArrayList ;
1011import java .util .Collection ;
1112import java .util .HashSet ;
1213import java .util .Iterator ;
14+ import java .util .List ;
1315
1416import org .hibernate .HibernateException ;
1517import org .hibernate .bytecode .enhance .spi .interceptor .LazyAttributeLoadingInterceptor ;
2931import org .hibernate .proxy .HibernateProxy ;
3032import org .hibernate .type .AssociationType ;
3133import org .hibernate .type .CollectionType ;
34+ import org .hibernate .type .ComponentType ;
3235import org .hibernate .type .CompositeType ;
3336import org .hibernate .type .EntityType ;
3437import 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