Skip to content

Commit b005b1b

Browse files
committed
HHH-20200 Handle table-per-class inheritance in soft-deletes
1 parent 5aa32be commit b005b1b

File tree

5 files changed

+187
-129
lines changed

5 files changed

+187
-129
lines changed

hibernate-core/src/main/java/org/hibernate/persister/entity/UnionSubclassEntityPersister.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,13 +236,25 @@ public TableGroup createRootTableGroup(
236236
SqlAliasBase sqlAliasBase,
237237
Supplier<Consumer<Predicate>> additionalPredicateCollectorAccess,
238238
SqlAstCreationState creationState) {
239-
return new UnionTableGroup(
239+
final var tableGroup = new UnionTableGroup(
240240
canUseInnerJoins,
241241
navigablePath,
242242
createPrimaryTableReference( sqlAliasBase, creationState ),
243243
this,
244244
explicitSourceAlias
245245
);
246+
final var softDeleteMapping = getSoftDeleteMapping();
247+
if ( additionalPredicateCollectorAccess != null && softDeleteMapping != null ) {
248+
final var tableReference =
249+
tableGroup.resolveTableReference( getSoftDeleteTableDetails().getTableName() );
250+
additionalPredicateCollectorAccess.get().accept(
251+
softDeleteMapping.createNonDeletedRestriction(
252+
tableReference,
253+
creationState.getSqlExpressionResolver()
254+
)
255+
);
256+
}
257+
return tableGroup;
246258
}
247259

248260
@Override

hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/SqmMutationStrategyHelper.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
*/
55
package org.hibernate.query.sqm.mutation.internal;
66

7+
import java.util.ArrayList;
8+
import java.util.List;
79
import java.util.function.BiConsumer;
810
import java.util.function.BiFunction;
911
import java.util.function.Consumer;
@@ -42,6 +44,7 @@
4244
import org.hibernate.metamodel.mapping.internal.EmbeddedAttributeMapping;
4345
import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping;
4446
import org.hibernate.persister.entity.EntityPersister;
47+
import org.hibernate.persister.entity.UnionSubclassEntityPersister;
4548
import org.hibernate.query.spi.QueryOptions;
4649
import org.hibernate.sql.ast.tree.AbstractUpdateOrDeleteStatement;
4750
import org.hibernate.sql.ast.tree.delete.DeleteStatement;
@@ -214,6 +217,24 @@ private static void visitCollectionTableDeletes(
214217
);
215218
}
216219

220+
/**
221+
* Returns the entity descriptors whose soft-delete tables need to be updated.
222+
* Only {@code TABLE_PER_CLASS} requires multiple targets (one per concrete
223+
* subtype table); other inheritance strategies share a single soft-delete table.
224+
*/
225+
public static List<EntityMappingType> softDeleteTargets(EntityMappingType entityDescriptor) {
226+
if ( entityDescriptor.getEntityPersister() instanceof UnionSubclassEntityPersister ) {
227+
// TABLE_PER_CLASS: each concrete subtype has its own table with the soft-delete column
228+
final var targets = new ArrayList<EntityMappingType>();
229+
targets.add( entityDescriptor );
230+
targets.addAll( entityDescriptor.getSubMappingTypes() );
231+
return targets;
232+
}
233+
else {
234+
return singletonList( entityDescriptor );
235+
}
236+
}
237+
217238
public static boolean isId(JdbcMappingContainer type) {
218239
return type instanceof EntityIdentifierMapping || type instanceof AttributeMapping attributeMapping
219240
&& isPartOfId( attributeMapping );

hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/cte/CteSoftDeleteHandler.java

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
import org.hibernate.engine.spi.SessionFactoryImplementor;
88
import org.hibernate.internal.util.MutableObject;
9+
import org.hibernate.metamodel.mapping.EntityMappingType;
910
import org.hibernate.metamodel.mapping.SoftDeleteMapping;
1011
import org.hibernate.metamodel.mapping.TableDetails;
1112
import org.hibernate.query.spi.DomainQueryExecutionContext;
@@ -27,6 +28,8 @@
2728
import java.util.Collections;
2829
import java.util.List;
2930

31+
import static org.hibernate.query.sqm.mutation.internal.SqmMutationStrategyHelper.softDeleteTargets;
32+
3033
/**
3134
* Specialized CteDeleteHandler for soft-delete handling
3235
*
@@ -50,8 +53,19 @@ protected void applyDmlOperations(
5053
CteStatement idSelectCte,
5154
SessionFactoryImplementor factory,
5255
TableGroup updatingTableGroup) {
53-
final SoftDeleteMapping softDeleteMapping = getEntityDescriptor().getSoftDeleteMapping();
54-
final TableDetails softDeleteTable = getEntityDescriptor().getSoftDeleteTableDetails();
56+
for ( var target : softDeleteTargets( getEntityDescriptor() ) ) {
57+
addSoftDeleteCte( statement, idSelectCte, factory, updatingTableGroup, target );
58+
}
59+
}
60+
61+
private void addSoftDeleteCte(
62+
CteContainer statement,
63+
CteStatement idSelectCte,
64+
SessionFactoryImplementor factory,
65+
TableGroup updatingTableGroup,
66+
EntityMappingType entityDescriptor) {
67+
final SoftDeleteMapping softDeleteMapping = entityDescriptor.getSoftDeleteMapping();
68+
final TableDetails softDeleteTable = entityDescriptor.getSoftDeleteTableDetails();
5569
final CteTable dmlResultCte = new CteTable(
5670
getCteTableName( softDeleteTable.getTableName() ),
5771
idSelectCte.getCteTable().getCteColumns()

hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/inline/InlineDeleteHandler.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,17 @@
99
import org.hibernate.engine.spi.SharedSessionContractImplementor;
1010
import org.hibernate.internal.util.MutableInteger;
1111
import org.hibernate.internal.util.MutableObject;
12+
import org.hibernate.metamodel.mapping.EntityMappingType;
1213
import org.hibernate.metamodel.mapping.ModelPart;
1314
import org.hibernate.metamodel.mapping.SelectableConsumer;
1415
import org.hibernate.metamodel.mapping.SoftDeleteMapping;
1516
import org.hibernate.metamodel.mapping.TableDetails;
16-
import org.hibernate.persister.entity.EntityPersister;
1717
import org.hibernate.query.spi.DomainQueryExecutionContext;
1818
import org.hibernate.query.sqm.internal.DomainParameterXref;
1919
import org.hibernate.query.sqm.internal.SqmJdbcExecutionContextAdapter;
2020
import org.hibernate.query.sqm.mutation.internal.DeleteHandler;
2121
import org.hibernate.query.sqm.mutation.internal.MatchingIdSelectionHelper;
22+
import static org.hibernate.query.sqm.mutation.internal.SqmMutationStrategyHelper.softDeleteTargets;
2223
import org.hibernate.query.sqm.mutation.internal.SqmMutationStrategyHelper;
2324
import org.hibernate.query.sqm.tree.delete.SqmDeleteStatement;
2425
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
@@ -62,7 +63,9 @@ protected InlineDeleteHandler(
6263

6364
final SoftDeleteMapping softDeleteMapping = getEntityDescriptor().getSoftDeleteMapping();
6465
if ( softDeleteMapping != null ) {
65-
tableDeleters.add( createSoftDeleter() );
66+
for ( var target : softDeleteTargets( getEntityDescriptor() ) ) {
67+
tableDeleters.add( createSoftDeleter( target ) );
68+
}
6669
}
6770
else {
6871
// delete from the tables
@@ -124,8 +127,7 @@ protected InlineDeleteHandler(
124127
this.tableDeleters = tableDeleters;
125128
}
126129

127-
private TableDeleter createSoftDeleter() {
128-
final EntityPersister entityDescriptor = getEntityDescriptor();
130+
private TableDeleter createSoftDeleter(EntityMappingType entityDescriptor) {
129131
final TableDetails softDeleteTable = entityDescriptor.getSoftDeleteTableDetails();
130132
final SoftDeleteMapping softDeleteMapping = entityDescriptor.getSoftDeleteMapping();
131133
assert softDeleteMapping != null;

0 commit comments

Comments
 (0)