Skip to content

Commit 0ecd5d8

Browse files
mbladelbeikov
authored andcommitted
HHH-17167 Also use @RowId for deletes when available
1 parent 3da12ca commit 0ecd5d8

File tree

4 files changed

+68
-108
lines changed

4 files changed

+68
-108
lines changed

hibernate-core/src/main/java/org/hibernate/annotations/RowId.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
/**
1616
* Specifies that a {@code rowid}-like column or pseudo-column should be
17-
* used as the row locator in SQL {@code update} statements for an entity,
17+
* used as the row locator in CRUD operations for an entity,
1818
* instead of the primary key of the table.
1919
* <p>
2020
* If the {@linkplain org.hibernate.dialect.Dialect SQL dialect} does

hibernate-core/src/main/java/org/hibernate/persister/entity/mutation/AbstractMutationCoordinator.java

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import org.hibernate.sql.model.ast.TableMutation;
2929
import org.hibernate.sql.model.ast.builder.ColumnValuesTableMutationBuilder;
3030
import org.hibernate.sql.model.ast.builder.MutationGroupBuilder;
31+
import org.hibernate.sql.model.ast.builder.RestrictedTableMutationBuilder;
3132
import org.hibernate.sql.model.internal.MutationOperationGroupFactory;
3233

3334
/**
@@ -165,4 +166,51 @@ protected void bindPartitionColumnValueBindings(
165166
}
166167
}
167168
}
169+
170+
protected static boolean needsRowId(AbstractEntityPersister entityPersister, EntityTableMapping tableMapping) {
171+
return entityPersister.getRowIdMapping() != null && tableMapping.isIdentifierTable();
172+
}
173+
174+
protected static void applyKeyRestriction(
175+
Object rowId,
176+
AbstractEntityPersister entityPersister,
177+
RestrictedTableMutationBuilder<?, ?> tableMutationBuilder,
178+
EntityTableMapping tableMapping) {
179+
if ( rowId != null && needsRowId( entityPersister, tableMapping ) ) {
180+
tableMutationBuilder.addKeyRestrictionLeniently( entityPersister.getRowIdMapping() );
181+
}
182+
else {
183+
tableMutationBuilder.addKeyRestrictions( tableMapping.getKeyMapping() );
184+
}
185+
}
186+
187+
protected void breakDownKeyJdbcValues(
188+
Object id,
189+
Object rowId,
190+
SharedSessionContractImplementor session,
191+
JdbcValueBindings jdbcValueBindings,
192+
EntityTableMapping tableMapping) {
193+
if ( rowId != null && needsRowId( entityPersister(), tableMapping ) ) {
194+
jdbcValueBindings.bindValue(
195+
rowId,
196+
tableMapping.getTableName(),
197+
entityPersister().getRowIdMapping().getRowIdName(),
198+
ParameterUsage.RESTRICT
199+
);
200+
}
201+
else {
202+
tableMapping.getKeyMapping().breakDownKeyJdbcValues(
203+
id,
204+
(jdbcValue, columnMapping) -> {
205+
jdbcValueBindings.bindValue(
206+
jdbcValue,
207+
tableMapping.getTableName(),
208+
columnMapping.getColumnName(),
209+
ParameterUsage.RESTRICT
210+
);
211+
},
212+
session
213+
);
214+
}
215+
}
168216
}

hibernate-core/src/main/java/org/hibernate/persister/entity/mutation/DeleteCoordinator.java

Lines changed: 16 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -12,21 +12,18 @@
1212
import org.hibernate.engine.jdbc.mutation.MutationExecutor;
1313
import org.hibernate.engine.jdbc.mutation.ParameterUsage;
1414
import org.hibernate.engine.jdbc.mutation.group.PreparedStatementDetails;
15-
import org.hibernate.engine.jdbc.mutation.spi.MutationExecutorService;
1615
import org.hibernate.engine.spi.EntityEntry;
1716
import org.hibernate.engine.spi.PersistenceContext;
1817
import org.hibernate.engine.spi.SessionFactoryImplementor;
1918
import org.hibernate.engine.spi.SharedSessionContractImplementor;
2019
import org.hibernate.metamodel.mapping.AttributeMapping;
2120
import org.hibernate.metamodel.mapping.AttributeMappingsList;
22-
import org.hibernate.metamodel.mapping.EntityRowIdMapping;
2321
import org.hibernate.metamodel.mapping.EntityVersionMapping;
2422
import org.hibernate.metamodel.mapping.SelectableMapping;
2523
import org.hibernate.persister.entity.AbstractEntityPersister;
2624
import org.hibernate.sql.model.MutationOperation;
2725
import org.hibernate.sql.model.MutationOperationGroup;
2826
import org.hibernate.sql.model.MutationType;
29-
import org.hibernate.sql.model.ast.ColumnValueBinding;
3027
import org.hibernate.sql.model.ast.ColumnValueBindingList;
3128
import org.hibernate.sql.model.ast.builder.MutationGroupBuilder;
3229
import org.hibernate.sql.model.ast.builder.RestrictedTableMutationBuilder;
@@ -52,7 +49,7 @@ public class DeleteCoordinator extends AbstractMutationCoordinator {
5249
public DeleteCoordinator(AbstractEntityPersister entityPersister, SessionFactoryImplementor factory) {
5350
super( entityPersister, factory );
5451

55-
this.staticOperationGroup = generateOperationGroup( null, true, null );
52+
this.staticOperationGroup = generateOperationGroup( "", null, true, null );
5653
this.batchKey = new BasicBatchKey( entityPersister.getEntityName() + "#DELETE" );
5754

5855
if ( !entityPersister.isVersioned() ) {
@@ -79,24 +76,23 @@ public void coordinateDelete(
7976

8077
final PersistenceContext persistenceContext = session.getPersistenceContextInternal();
8178
final EntityEntry entry = persistenceContext.getEntry( entity );
82-
final Object[] loadedState = entry != null && isImpliedOptimisticLocking ? entry.getLoadedState() : null;
83-
final Object rowId = entry != null && entityPersister().hasRowId() ? entry.getRowId() : null;
79+
final Object[] loadedState = entry != null ? entry.getLoadedState() : null;
80+
final Object rowId = entry != null ? entry.getRowId() : null;
8481

85-
if ( ( isImpliedOptimisticLocking && loadedState != null ) || rowId != null ) {
86-
doDynamicDelete( entity, id, rowId, loadedState, session );
82+
if ( ( isImpliedOptimisticLocking && loadedState != null ) || ( rowId == null && entityPersister().hasRowId() ) ) {
83+
doDynamicDelete( entity, id, loadedState, session );
8784
}
8885
else {
89-
doStaticDelete( entity, id, entry == null ? null : entry.getLoadedState(), version, session );
86+
doStaticDelete( entity, id, rowId, loadedState, version, session );
9087
}
9188
}
9289

9390
protected void doDynamicDelete(
9491
Object entity,
9592
Object id,
96-
Object rowId,
9793
Object[] loadedState,
9894
SharedSessionContractImplementor session) {
99-
final MutationOperationGroup operationGroup = generateOperationGroup( loadedState, true, session );
95+
final MutationOperationGroup operationGroup = generateOperationGroup( null, loadedState, true, session );
10096

10197
final MutationExecutor mutationExecutor = executor( session, operationGroup );
10298

@@ -110,7 +106,7 @@ protected void doDynamicDelete(
110106

111107
applyLocking( null, loadedState, mutationExecutor, session );
112108

113-
applyId( id, rowId, mutationExecutor, operationGroup, session );
109+
applyId( id, null, mutationExecutor, operationGroup, session );
114110

115111
try {
116112
mutationExecutor.execute(
@@ -217,14 +213,11 @@ protected void applyId(
217213
MutationExecutor mutationExecutor,
218214
MutationOperationGroup operationGroup,
219215
SharedSessionContractImplementor session) {
220-
221216
final JdbcValueBindings jdbcValueBindings = mutationExecutor.getJdbcValueBindings();
222-
final EntityRowIdMapping rowIdMapping = entityPersister().getRowIdMapping();
223-
224217
for ( int position = 0; position < operationGroup.getNumberOfOperations(); position++ ) {
225218
final MutationOperation jdbcMutation = operationGroup.getOperation( position );
226219
final EntityTableMapping tableDetails = (EntityTableMapping) jdbcMutation.getTableDetails();
227-
breakDownIdJdbcValues( id, rowId, session, jdbcValueBindings, rowIdMapping, tableDetails );
220+
breakDownKeyJdbcValues( id, rowId, session, jdbcValueBindings, tableDetails );
228221
final PreparedStatementDetails statementDetails = mutationExecutor.getPreparedStatementDetails( tableDetails.getTableName() );
229222
if ( statementDetails != null ) {
230223
// force creation of the PreparedStatement
@@ -234,40 +227,10 @@ protected void applyId(
234227
}
235228
}
236229

237-
private static void breakDownIdJdbcValues(
238-
Object id,
239-
Object rowId,
240-
SharedSessionContractImplementor session,
241-
JdbcValueBindings jdbcValueBindings,
242-
EntityRowIdMapping rowIdMapping,
243-
EntityTableMapping tableDetails) {
244-
if ( rowId != null && rowIdMapping != null && tableDetails.isIdentifierTable() ) {
245-
jdbcValueBindings.bindValue(
246-
rowId,
247-
tableDetails.getTableName(),
248-
rowIdMapping.getRowIdName(),
249-
ParameterUsage.RESTRICT
250-
);
251-
}
252-
else {
253-
tableDetails.getKeyMapping().breakDownKeyJdbcValues(
254-
id,
255-
(jdbcValue, columnMapping) -> {
256-
jdbcValueBindings.bindValue(
257-
jdbcValue,
258-
tableDetails.getTableName(),
259-
columnMapping.getColumnName(),
260-
ParameterUsage.RESTRICT
261-
);
262-
},
263-
session
264-
);
265-
}
266-
}
267-
268230
protected void doStaticDelete(
269231
Object entity,
270232
Object id,
233+
Object rowId,
271234
Object[] loadedState,
272235
Object version,
273236
SharedSessionContractImplementor session) {
@@ -299,7 +262,7 @@ protected void doStaticDelete(
299262

300263
bindPartitionColumnValueBindings( loadedState, session, jdbcValueBindings );
301264

302-
applyId( id, null, mutationExecutor, staticOperationGroup, session );
265+
applyId( id, rowId, mutationExecutor, staticOperationGroup, session );
303266

304267
mutationExecutor.execute(
305268
entity,
@@ -321,13 +284,14 @@ protected void doStaticDelete(
321284

322285
protected MutationOperationGroup resolveNoVersionDeleteGroup(SharedSessionContractImplementor session) {
323286
if ( noVersionDeleteGroup == null ) {
324-
noVersionDeleteGroup = generateOperationGroup( null, false, session );
287+
noVersionDeleteGroup = generateOperationGroup( "", null, false, session );
325288
}
326289

327290
return noVersionDeleteGroup;
328291
}
329292

330293
protected MutationOperationGroup generateOperationGroup(
294+
Object rowId,
331295
Object[] loadedState,
332296
boolean applyVersion,
333297
SharedSessionContractImplementor session) {
@@ -340,21 +304,22 @@ protected MutationOperationGroup generateOperationGroup(
340304
deleteGroupBuilder.addTableDetailsBuilder( tableDeleteBuilder );
341305
} );
342306

343-
applyTableDeleteDetails( deleteGroupBuilder, loadedState, applyVersion, session );
307+
applyTableDeleteDetails( deleteGroupBuilder, rowId, loadedState, applyVersion, session );
344308

345309
return createOperationGroup( null, deleteGroupBuilder.buildMutationGroup() );
346310
}
347311

348312
private void applyTableDeleteDetails(
349313
MutationGroupBuilder deleteGroupBuilder,
314+
Object rowId,
350315
Object[] loadedState,
351316
boolean applyVersion,
352317
SharedSessionContractImplementor session) {
353318
// first, the table key column(s)
354319
deleteGroupBuilder.forEachTableMutationBuilder( (builder) -> {
355320
final EntityTableMapping tableMapping = (EntityTableMapping) builder.getMutatingTable().getTableMapping();
356321
final TableDeleteBuilder tableDeleteBuilder = (TableDeleteBuilder) builder;
357-
applyKeyDetails( tableDeleteBuilder, tableMapping );
322+
applyKeyRestriction( rowId, entityPersister(), tableDeleteBuilder, tableMapping );
358323
} );
359324

360325
if ( applyVersion ) {
@@ -382,10 +347,6 @@ private void applyTableDeleteDetails(
382347
// todo (6.2) : apply where + where-fragments
383348
}
384349

385-
private static void applyKeyDetails(TableDeleteBuilder tableDeleteBuilder, EntityTableMapping tableMapping) {
386-
tableDeleteBuilder.addKeyRestrictions( tableMapping.getKeyMapping() );
387-
}
388-
389350
protected void applyOptimisticLocking(
390351
MutationGroupBuilder mutationGroupBuilder,
391352
Object[] loadedState,

hibernate-core/src/main/java/org/hibernate/persister/entity/mutation/UpdateCoordinatorStandard.java

Lines changed: 3 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,8 @@
77
package org.hibernate.persister.entity.mutation;
88

99
import java.util.ArrayList;
10-
import java.util.HashSet;
1110
import java.util.List;
1211
import java.util.Locale;
13-
import java.util.Set;
1412

1513
import org.hibernate.AssertionFailure;
1614
import org.hibernate.HibernateException;
@@ -22,7 +20,6 @@
2220
import org.hibernate.engine.jdbc.mutation.JdbcValueBindings;
2321
import org.hibernate.engine.jdbc.mutation.MutationExecutor;
2422
import org.hibernate.engine.jdbc.mutation.ParameterUsage;
25-
import org.hibernate.sql.model.internal.MutationOperationGroupFactory;
2623
import org.hibernate.engine.jdbc.mutation.internal.MutationQueryOptions;
2724
import org.hibernate.engine.jdbc.mutation.internal.NoBatchKeyAccess;
2825
import org.hibernate.engine.jdbc.mutation.spi.BatchKeyAccess;
@@ -37,7 +34,6 @@
3734
import org.hibernate.internal.util.collections.CollectionHelper;
3835
import org.hibernate.metamodel.mapping.AttributeMapping;
3936
import org.hibernate.metamodel.mapping.AttributeMappingsList;
40-
import org.hibernate.metamodel.mapping.EntityRowIdMapping;
4137
import org.hibernate.metamodel.mapping.EntityVersionMapping;
4238
import org.hibernate.metamodel.mapping.SelectableMapping;
4339
import org.hibernate.metamodel.mapping.SingularAttributeMapping;
@@ -53,6 +49,7 @@
5349
import org.hibernate.sql.model.ast.builder.TableUpdateBuilder;
5450
import org.hibernate.sql.model.ast.builder.TableUpdateBuilderSkipped;
5551
import org.hibernate.sql.model.ast.builder.TableUpdateBuilderStandard;
52+
import org.hibernate.sql.model.internal.MutationOperationGroupFactory;
5653
import org.hibernate.sql.model.jdbc.JdbcMutationOperation;
5754
import org.hibernate.tuple.entity.EntityMetamodel;
5855

@@ -874,38 +871,6 @@ private static void optimisticLock(
874871
} );
875872
}
876873

877-
private void breakDownKeyJdbcValues(
878-
Object id,
879-
Object rowId,
880-
SharedSessionContractImplementor session,
881-
JdbcValueBindings jdbcValueBindings,
882-
EntityTableMapping tableMapping) {
883-
// if the mutation is against the identifier table and we need to use row-id...
884-
if ( tableMapping.isIdentifierTable() && entityPersister().hasRowId() && rowId != null ) {
885-
// todo (mutation) : make sure the SQL uses row-id in this case
886-
jdbcValueBindings.bindValue(
887-
rowId,
888-
tableMapping.getTableName(),
889-
entityPersister().getRowIdMapping().getRowIdName(),
890-
ParameterUsage.RESTRICT
891-
);
892-
}
893-
else {
894-
tableMapping.getKeyMapping().breakDownKeyJdbcValues(
895-
id,
896-
(jdbcValue, columnMapping) -> {
897-
jdbcValueBindings.bindValue(
898-
jdbcValue,
899-
tableMapping.getTableName(),
900-
columnMapping.getColumnName(),
901-
ParameterUsage.RESTRICT
902-
);
903-
},
904-
session
905-
);
906-
}
907-
}
908-
909874
private static void decomposeAttributeMapping(
910875
SharedSessionContractImplementor session,
911876
JdbcValueBindings jdbcValueBindings,
@@ -1100,7 +1065,6 @@ private void applyTableUpdateDetails(
11001065
DirtinessChecker dirtinessChecker,
11011066
SharedSessionContractImplementor session) {
11021067
final EntityVersionMapping versionMapping = entityPersister().getVersionMapping();
1103-
final EntityRowIdMapping rowIdMapping = entityPersister().getRowIdMapping();
11041068
final AttributeMappingsList attributeMappings = entityPersister().getAttributeMappings();
11051069
final boolean[] versionability = entityPersister().getPropertyVersionability();
11061070
final OptimisticLockStyle optimisticLockStyle = entityPersister().optimisticLockStyle();
@@ -1155,7 +1119,7 @@ private void applyTableUpdateDetails(
11551119
updateGroupBuilder.forEachTableMutationBuilder( (builder) -> {
11561120
final EntityTableMapping tableMapping = (EntityTableMapping) builder.getMutatingTable().getTableMapping();
11571121
final TableUpdateBuilder<?> tableUpdateBuilder = (TableUpdateBuilder<?>) builder;
1158-
applyKeyRestriction( rowId, rowIdMapping, tableUpdateBuilder, tableMapping );
1122+
applyKeyRestriction( rowId, entityPersister(), tableUpdateBuilder, tableMapping );
11591123
applyPartitionKeyRestriction( tableUpdateBuilder );
11601124
} );
11611125
}
@@ -1177,19 +1141,6 @@ private void applyPartitionKeyRestriction(TableUpdateBuilder<?> tableUpdateBuild
11771141
}
11781142
}
11791143

1180-
private static void applyKeyRestriction(
1181-
Object rowId,
1182-
EntityRowIdMapping rowIdMapping,
1183-
TableUpdateBuilder<?> tableUpdateBuilder,
1184-
EntityTableMapping tableMapping) {
1185-
if ( rowIdMapping != null && rowId != null && tableMapping.isIdentifierTable() ) {
1186-
tableUpdateBuilder.addKeyRestrictionLeniently( rowIdMapping );
1187-
}
1188-
else {
1189-
tableUpdateBuilder.addKeyRestrictions( tableMapping.getKeyMapping() );
1190-
}
1191-
}
1192-
11931144
private static void applyAttributeLockingDetails(
11941145
Object[] oldValues,
11951146
SharedSessionContractImplementor session,
@@ -1344,7 +1295,7 @@ else if ( dirtyAttributeIndexes != null ) {
13441295
|| entityPersister().optimisticLockStyle() == DIRTY ) {
13451296
tablesNeedingDynamicUpdate.add( tableMapping );
13461297
}
1347-
else if ( rowId == null && entityPersister().getRowIdMapping() != null && tableMapping.isIdentifierTable() ) {
1298+
else if ( rowId == null && needsRowId( entityPersister(), tableMapping ) ) {
13481299
tablesNeedingDynamicUpdate.add( tableMapping );
13491300
}
13501301
}

0 commit comments

Comments
 (0)