@@ -274,10 +274,15 @@ public void decompose(
274274 final boolean isBeingDeleted = decompositionContext != null
275275 && decompositionContext .isBeingDeletedInCurrentFlush ( entity );
276276
277- for ( Map .Entry <String , LogicalTableUpdate <?>> entry : effectiveGroup .entrySet () ) {
278- var operation = entry .getValue ().createMutationOperation (null , sessionFactory );
279- var tableMapping = (TableDescriptorAsTableMapping ) operation .getTableDetails ();
280- var tableDescriptor = (EntityTableDescriptor ) tableMapping .descriptor ();
277+ for ( var tableDescriptor : entityPersister .getTableDescriptors () ) {
278+ if ( tableDescriptor .isInverse () ) {
279+ continue ;
280+ }
281+ final var tableUpdate = effectiveGroup .get ( tableDescriptor .name () );
282+ if ( tableUpdate == null ) {
283+ continue ;
284+ }
285+ var operation = tableUpdate .createMutationOperation ( null , sessionFactory );
281286
282287 // For static updates, only execute secondary tables when one of their
283288 // attributes actually drove the update. Static mutation groups may
@@ -292,9 +297,9 @@ public void decompose(
292297
293298 // If this entity is being deleted in the same flush, skip UPDATEs to optional tables.
294299 // These UPDATEs can re-insert rows that were just deleted, causing constraint violations.
295- // DELETE → DELETE edges ensure proper FK ordering, so UPDATEs are unnecessary.
300+ // DELETE -> DELETE edges ensure proper FK ordering, so UPDATEs are unnecessary.
296301 //
297- // Technically we could alo skip updates to the primary table if no foreign keys are being nullified.
302+ // Technically we could also skip updates to the primary table if no foreign keys are being nullified.
298303 // This should be a rare enough occurrence that it is probably not worth even checking for.
299304 if ( isBeingDeleted && tableDescriptor .isOptional () ) {
300305 continue ;
@@ -608,6 +613,14 @@ private Map<String, LogicalTableUpdate<?>> generateStaticOperations() {
608613 }
609614
610615 private TableUpdateBuilder <?> createTableUpdateBuilder (TableDescriptor tableDescriptor ) {
616+ if ( tableDescriptor instanceof EntityTableDescriptor entityTableDescriptor
617+ && entityTableDescriptor .isIdentifierTable () ) {
618+ final var delegate = entityPersister .getUpdateDelegate ();
619+ if ( delegate != null ) {
620+ return (TableUpdateBuilder <?>) delegate .createTableMutationBuilder ( null , sessionFactory );
621+ }
622+ }
623+
611624 return new TableUpdateBuilderStandard <>(
612625 entityPersister ,
613626 new MutatingTableReference ( getTableMappingAdapter ( tableDescriptor ) ),
@@ -683,14 +696,8 @@ protected Map<String, LogicalTableUpdate<?>> generateDynamicUpdateOperations(
683696 private void applyStaticUpdateDetails (Map <String , TableUpdateBuilder <?>> builders ) {
684697 final boolean [] propertyUpdateability = entityPersister .getPropertyUpdateability ();
685698
686- builders .forEach ( (name , builder ) -> {
687- // Get the TableDescriptor from the adapter
688- final var tableMapping = (TableDescriptorAsTableMapping ) builder .getMutatingTable ().getTableMapping ();
689- final var tableDescriptor = (EntityTableDescriptor ) tableMapping .descriptor ();
690- // Skip inverse tables
691- if (tableDescriptor .isInverse ()) {
692- return ;
693- }
699+ entityPersister .forEachMutableTableDescriptor ( (tableDescriptor ) -> {
700+ final var builder = builders .get ( tableDescriptor .name () );
694701
695702 // Apply SET clause columns for attributes
696703 for ( int i = 0 ; i < tableDescriptor .attributes ().size (); i ++ ) {
@@ -710,10 +717,10 @@ private void applyStaticUpdateDetails(Map<String, TableUpdateBuilder<?>> builder
710717 }
711718
712719 // Apply WHERE clause - key restrictions
713- applyKeyRestriction ( builder );
720+ applyKeyRestriction ( tableDescriptor , builder );
714721
715722 // Apply optimistic locking
716- applyOptimisticLocking ( builder , null , null , null );
723+ applyOptimisticLocking ( tableDescriptor , builder , null , null , null );
717724 } );
718725
719726 // Apply partitioned selection restrictions if needed
@@ -781,12 +788,9 @@ private void applyDynamicUpdateDetails(
781788 UpdateValuesAnalysis valuesAnalysis ,
782789 boolean [] updateable ,
783790 SharedSessionContractImplementor session ) {
784- builders .forEach ( (name , builder ) -> {
785- // Get the TableDescriptor from the adapter
786- final var tableMapping = (TableDescriptorAsTableMapping ) builder .getMutatingTable ().getTableMapping ();
787- final var tableDescriptor = (EntityTableDescriptor ) tableMapping .descriptor ();
788- // Skip inverse tables
789- if (tableDescriptor .isInverse ()) {
791+ entityPersister .forEachMutableTableDescriptor ( (tableDescriptor ) -> {
792+ final var builder = builders .get ( tableDescriptor .name () );
793+ if ( builder == null ) {
790794 return ;
791795 }
792796
@@ -803,10 +807,10 @@ private void applyDynamicUpdateDetails(
803807 }
804808
805809 // Apply WHERE clause - key restrictions
806- applyKeyRestriction ( builder , rowId );
810+ applyKeyRestriction ( tableDescriptor , builder , rowId );
807811
808812 // Apply optimistic locking
809- applyOptimisticLocking ( builder , previousState , valuesAnalysis , session );
813+ applyOptimisticLocking ( tableDescriptor , builder , previousState , valuesAnalysis , session );
810814 } );
811815
812816 // Apply partitioned selection restrictions if needed
@@ -841,17 +845,13 @@ private boolean shouldIncludeInDynamicUpdate(
841845 return true ;
842846 }
843847
844- private void applyKeyRestriction (TableUpdateBuilder <?> tableUpdateBuilder ) {
845- applyKeyRestriction ( tableUpdateBuilder , null );
848+ private void applyKeyRestriction (EntityTableDescriptor tableDescriptor , TableUpdateBuilder <?> tableUpdateBuilder ) {
849+ applyKeyRestriction ( tableDescriptor , tableUpdateBuilder , null );
846850 }
847851
848- private void applyKeyRestriction (TableUpdateBuilder <?> tableUpdateBuilder , Object rowId ) {
849- // Get the TableDescriptor from the adapter
850- final var tableMapping = (TableDescriptorAsTableMapping ) tableUpdateBuilder .getMutatingTable ().getTableMapping ();
851- final var tableDescriptor = tableMapping .descriptor ();
852+ private void applyKeyRestriction (EntityTableDescriptor tableDescriptor , TableUpdateBuilder <?> tableUpdateBuilder , Object rowId ) {
852853 if ( rowId != null
853- && tableDescriptor instanceof EntityTableDescriptor entityTableDescriptor
854- && entityTableDescriptor .isIdentifierTable ()
854+ && tableDescriptor .isIdentifierTable ()
855855 && entityPersister .getRowIdMapping () != null ) {
856856 tableUpdateBuilder .addKeyRestrictionLeniently ( entityPersister .getRowIdMapping () );
857857 }
@@ -861,25 +861,23 @@ private void applyKeyRestriction(TableUpdateBuilder<?> tableUpdateBuilder, Objec
861861 }
862862
863863 private void applyOptimisticLocking (
864+ EntityTableDescriptor tableDescriptor ,
864865 TableUpdateBuilder <?> tableUpdateBuilder ,
865866 Object [] previousState ,
866867 UpdateValuesAnalysis valuesAnalysis ,
867868 SharedSessionContractImplementor session ) {
868869 final var optimisticLockStyle = entityPersister .optimisticLockStyle ();
869870
870871 if ( optimisticLockStyle .isVersion () && entityPersister .getVersionMapping () != null ) {
871- applyVersionBasedOptLocking ( tableUpdateBuilder );
872+ applyVersionBasedOptLocking ( tableDescriptor , tableUpdateBuilder );
872873 }
873874 else if ( optimisticLockStyle .isAllOrDirty () ) {
874- applyNonVersionOptLocking ( tableUpdateBuilder , previousState , optimisticLockStyle , valuesAnalysis , session );
875+ applyNonVersionOptLocking ( tableDescriptor , tableUpdateBuilder , previousState , optimisticLockStyle , valuesAnalysis , session );
875876 }
876877 }
877878
878- private void applyVersionBasedOptLocking (TableUpdateBuilder <?> tableUpdateBuilder ) {
879+ private void applyVersionBasedOptLocking (EntityTableDescriptor tableDescriptor , TableUpdateBuilder <?> tableUpdateBuilder ) {
879880 final var versionMapping = entityPersister .getVersionMapping ();
880- // Get the TableDescriptor from the adapter
881- final var tableMapping = (TableDescriptorAsTableMapping ) tableUpdateBuilder .getMutatingTable ().getTableMapping ();
882- final var tableDescriptor = tableMapping .descriptor ();
883881 if ( versionMapping != null
884882 && tableDescriptor .name ().equals (
885883 versionMapping .getContainingTableExpression () ) ) {
@@ -888,6 +886,7 @@ private void applyVersionBasedOptLocking(TableUpdateBuilder<?> tableUpdateBuilde
888886 }
889887
890888 private void applyNonVersionOptLocking (
889+ EntityTableDescriptor tableDescriptor ,
891890 TableUpdateBuilder <?> tableUpdateBuilder ,
892891 Object [] previousState ,
893892 OptimisticLockStyle optimisticLockStyle ,
@@ -902,9 +901,6 @@ private void applyNonVersionOptLocking(
902901 }
903902
904903 final boolean [] versionability = entityPersister .getPropertyVersionability ();
905- // Get the TableDescriptor from the adapter
906- final var tableMapping = (TableDescriptorAsTableMapping ) tableUpdateBuilder .getMutatingTable ().getTableMapping ();
907- final var tableDescriptor = (EntityTableDescriptor ) tableMapping .descriptor ();
908904
909905 for ( int i = 0 ; i < tableDescriptor .attributes ().size (); i ++ ) {
910906 var attribute = tableDescriptor .attributes ().get ( i );
0 commit comments