Skip to content

Commit d3b777f

Browse files
committed
HHH-19925 - Locking root(s) should be based on select-clause, not from-clause
1 parent 8c97acd commit d3b777f

File tree

20 files changed

+171
-112
lines changed

20 files changed

+171
-112
lines changed

hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/DerbyDialect.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableInsertStrategy;
6060
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
6161
import org.hibernate.service.ServiceRegistry;
62+
import org.hibernate.spi.NavigablePath;
6263
import org.hibernate.sql.ast.SqlAstNodeRenderingMode;
6364
import org.hibernate.sql.ast.SqlAstTranslator;
6465
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
@@ -85,6 +86,7 @@
8586
import java.sql.SQLException;
8687
import java.sql.Types;
8788
import java.util.Locale;
89+
import java.util.Set;
8890

8991
import static org.hibernate.type.SqlTypes.BINARY;
9092
import static org.hibernate.type.SqlTypes.BLOB;
@@ -564,8 +566,9 @@ public LockingSupport getLockingSupport() {
564566
protected LockingClauseStrategy buildLockingClauseStrategy(
565567
PessimisticLockKind lockKind,
566568
RowLockStrategy rowLockStrategy,
567-
LockOptions lockOptions) {
568-
return new DerbyLockingClauseStrategy( this, lockKind, rowLockStrategy, lockOptions );
569+
LockOptions lockOptions,
570+
Set<NavigablePath> rootPathsForLocking) {
571+
return new DerbyLockingClauseStrategy( this, lockKind, rowLockStrategy, lockOptions, rootPathsForLocking );
569572
}
570573

571574
@Override

hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/DerbyLegacyDialect.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableInsertStrategy;
5959
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
6060
import org.hibernate.service.ServiceRegistry;
61+
import org.hibernate.spi.NavigablePath;
6162
import org.hibernate.sql.ast.SqlAstNodeRenderingMode;
6263
import org.hibernate.sql.ast.SqlAstTranslator;
6364
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
@@ -85,6 +86,7 @@
8586
import java.sql.DatabaseMetaData;
8687
import java.sql.SQLException;
8788
import java.sql.Types;
89+
import java.util.Set;
8890

8991
import static org.hibernate.type.SqlTypes.BINARY;
9092
import static org.hibernate.type.SqlTypes.BLOB;
@@ -551,8 +553,9 @@ public boolean supportsCommentOn() {
551553
protected LockingClauseStrategy buildLockingClauseStrategy(
552554
PessimisticLockKind lockKind,
553555
RowLockStrategy rowLockStrategy,
554-
LockOptions lockOptions) {
555-
return new DerbyLockingClauseStrategy( this, lockKind, rowLockStrategy, lockOptions );
556+
LockOptions lockOptions,
557+
Set<NavigablePath> rootPathsForLocking) {
558+
return new DerbyLockingClauseStrategy( this, lockKind, rowLockStrategy, lockOptions, rootPathsForLocking );
556559
}
557560

558561
@Override

hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/DerbyLockingClauseStrategy.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,13 @@
77
import org.hibernate.LockOptions;
88
import org.hibernate.dialect.Dialect;
99
import org.hibernate.dialect.RowLockStrategy;
10+
import org.hibernate.spi.NavigablePath;
1011
import org.hibernate.sql.ast.internal.PessimisticLockKind;
1112
import org.hibernate.sql.ast.internal.StandardLockingClauseStrategy;
1213
import org.hibernate.sql.ast.spi.SqlAppender;
1314

15+
import java.util.Set;
16+
1417
/**
1518
* StandardLockingClauseStrategy subclass, specific for Derby.
1619
*
@@ -21,8 +24,9 @@ public DerbyLockingClauseStrategy(
2124
Dialect dialect,
2225
PessimisticLockKind lockKind,
2326
RowLockStrategy rowLockStrategy,
24-
LockOptions lockOptions) {
25-
super( dialect, lockKind, rowLockStrategy, lockOptions );
27+
LockOptions lockOptions,
28+
Set<NavigablePath> rootPathsForLocking) {
29+
super( dialect, lockKind, rowLockStrategy, lockOptions, rootPathsForLocking );
2630
}
2731

2832
@Override

hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/TeradataDialect.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import org.hibernate.query.sqm.mutation.internal.temptable.GlobalTemporaryTableMutationStrategy;
4141
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableInsertStrategy;
4242
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
43+
import org.hibernate.spi.NavigablePath;
4344
import org.hibernate.sql.ForUpdateFragment;
4445
import org.hibernate.sql.ast.SqlAstTranslator;
4546
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
@@ -65,6 +66,7 @@
6566
import java.sql.SQLException;
6667
import java.sql.Types;
6768
import java.util.Map;
69+
import java.util.Set;
6870

6971
import static org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtractor.extractUsingTemplate;
7072
import static org.hibernate.type.SqlTypes.BIGINT;
@@ -529,13 +531,14 @@ public LockingSupport getLockingSupport() {
529531
protected LockingClauseStrategy buildLockingClauseStrategy(
530532
PessimisticLockKind lockKind,
531533
RowLockStrategy rowLockStrategy,
532-
LockOptions lockOptions) {
534+
LockOptions lockOptions,
535+
Set<NavigablePath> rootPathsForLocking) {
533536
if ( getVersion().isBefore( 14 ) ) {
534537
return NonLockingClauseStrategy.NON_CLAUSE_STRATEGY;
535538
}
536539
// we'll reuse the StandardLockingClauseStrategy for the collecting
537540
// aspect and just handle the special rendering in the SQL AST translator
538-
return super.buildLockingClauseStrategy( lockKind, rowLockStrategy, lockOptions );
541+
return super.buildLockingClauseStrategy( lockKind, rowLockStrategy, lockOptions, rootPathsForLocking );
539542
}
540543

541544
@Override

hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@
114114
import org.hibernate.query.sqm.sql.SqmTranslatorFactory;
115115
import org.hibernate.service.ServiceRegistry;
116116
import org.hibernate.service.spi.ServiceRegistryImplementor;
117+
import org.hibernate.spi.NavigablePath;
117118
import org.hibernate.sql.ForUpdateFragment;
118119
import org.hibernate.sql.ast.SqlAstNodeRenderingMode;
119120
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
@@ -2369,14 +2370,15 @@ public LockingClauseStrategy getLockingClauseStrategy(QuerySpec querySpec, LockO
23692370
default -> throw new IllegalStateException( "Should never happen due to checks above" );
23702371
}
23712372

2372-
return buildLockingClauseStrategy( lockKind, rowLockStrategy, lockOptions );
2373+
return buildLockingClauseStrategy( lockKind, rowLockStrategy, lockOptions, querySpec.getRootPathsForLocking() );
23732374
}
23742375

23752376
protected LockingClauseStrategy buildLockingClauseStrategy(
23762377
PessimisticLockKind lockKind,
23772378
RowLockStrategy rowLockStrategy,
2378-
LockOptions lockOptions) {
2379-
return new StandardLockingClauseStrategy( this, lockKind, rowLockStrategy, lockOptions );
2379+
LockOptions lockOptions,
2380+
Set<NavigablePath> rootPathsForLocking) {
2381+
return new StandardLockingClauseStrategy( this, lockKind, rowLockStrategy, lockOptions, rootPathsForLocking );
23802382
}
23812383

23822384
/**

hibernate-core/src/main/java/org/hibernate/dialect/lock/internal/SqlAstBasedLockingStrategy.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,11 @@ public void lock(
7373
lockOptions.setScope( lockScope );
7474
lockOptions.setTimeOut( timeout );
7575

76-
final var rootQuerySpec = new QuerySpec( true );
7776
final var entityPath = new NavigablePath( entityToLock.getRootPathName() );
77+
78+
final var rootQuerySpec = new QuerySpec( true );
79+
rootQuerySpec.applyRootPathForLocking( entityPath );
80+
7881
final var idMapping = entityToLock.getIdentifierMapping();
7982

8083
// NOTE: there are 2 possible ways to handle the select list for the query...
@@ -154,7 +157,7 @@ public void lock(
154157
);
155158
}
156159

157-
final var selectStatement = new SelectStatement( rootQuerySpec, List.of( idResult ), List.of( entityPath ) );
160+
final var selectStatement = new SelectStatement( rootQuerySpec, List.of( idResult ) );
158161
final JdbcSelect selectOperation =
159162
session.getDialect().getSqlAstTranslatorFactory()
160163
.buildSelectTranslator( factory, selectStatement )

hibernate-core/src/main/java/org/hibernate/loader/ast/internal/AbstractNaturalIdLoader.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ public Object resolveNaturalIdToId(Object naturalIdValue, SharedSessionContractI
215215
return executeNaturalIdQuery(
216216
naturalIdValue,
217217
LockOptions.NONE,
218-
new SelectStatement( rootQuerySpec, singletonList( domainResult ), List.of() ),
218+
new SelectStatement( rootQuerySpec, singletonList( domainResult ) ),
219219
rootTableGroup,
220220
rootQuerySpec::applyPredicate,
221221
sqlAstCreationState,

hibernate-core/src/main/java/org/hibernate/loader/ast/internal/DatabaseSnapshotExecutor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ class DatabaseSnapshotExecutor {
128128
}
129129
);
130130

131-
final var selectStatement = new SelectStatement( rootQuerySpec, domainResults, List.of() );
131+
final var selectStatement = new SelectStatement( rootQuerySpec, domainResults );
132132
jdbcSelect =
133133
sessionFactory.getJdbcServices().getJdbcEnvironment().getSqlAstTranslatorFactory()
134134
.buildSelectTranslator( sessionFactory, selectStatement )

hibernate-core/src/main/java/org/hibernate/loader/ast/internal/LoaderSelectBuilder.java

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,8 @@ public static SelectStatement createSelectBySingleArrayParameter(
148148
final var sqlAstCreationState = builder.createSqlAstCreationState( rootQuerySpec );
149149

150150
final var rootNavigablePath = new NavigablePath( loadable.getRootPathName() );
151+
rootQuerySpec.applyRootPathForLocking( rootNavigablePath );
152+
151153
final var rootTableGroup =
152154
builder.buildRootTableGroup( rootNavigablePath, rootQuerySpec, sqlAstCreationState );
153155

@@ -177,7 +179,7 @@ public static SelectStatement createSelectBySingleArrayParameter(
177179
builder.applyFiltering( rootQuerySpec, rootTableGroup, (Restrictable) loadable, sqlAstCreationState );
178180
}
179181

180-
return new SelectStatement( rootQuerySpec, domainResults, List.of( rootNavigablePath ) );
182+
return new SelectStatement( rootQuerySpec, domainResults );
181183
}
182184

183185
private static void applyArrayParamRestriction(
@@ -464,6 +466,8 @@ private SelectStatement generateSelect() {
464466
final var rootNavigablePath = new NavigablePath( loadable.getRootPathName() );
465467

466468
final var rootQuerySpec = new QuerySpec( true );
469+
rootQuerySpec.applyRootPathForLocking( rootNavigablePath );
470+
467471
final var sqlAstCreationState = createSqlAstCreationState( rootQuerySpec );
468472

469473
final var rootTableGroup = buildRootTableGroup( rootNavigablePath, rootQuerySpec, sqlAstCreationState );
@@ -505,7 +509,7 @@ else if ( cachedDomainResult != null ) {
505509
applyFiltering( rootQuerySpec, rootTableGroup, (Restrictable) loadable, sqlAstCreationState );
506510
}
507511

508-
return new SelectStatement( rootQuerySpec, domainResults, List.of( rootNavigablePath ) );
512+
return new SelectStatement( rootQuerySpec, domainResults );
509513
}
510514

511515
private List<DomainResult<?>> buildRequestedDomainResults(
@@ -980,12 +984,11 @@ private SelectStatement generateSelect(SubselectFetch subselect) {
980984
// - so `loadable` is the owner entity-descriptor and the `partsToSelect` is the collection
981985

982986
assert loadable instanceof PluralAttributeMapping;
983-
984987
final var attributeMapping = (PluralAttributeMapping) loadable;
985988

986-
final var rootQuerySpec = new QuerySpec( true );
987-
988989
final var rootNavigablePath = new NavigablePath( loadable.getRootPathName() );
990+
final var rootQuerySpec = new QuerySpec( true );
991+
rootQuerySpec.applyRootPathForLocking( rootNavigablePath );
989992

990993
// We need to initialize the acronymMap based on subselect.getLoadingSqlAst() to avoid alias collisions
991994
final var tableReferences = AliasCollector.getTableReferences( subselect.getLoadingSqlAst() );
@@ -1024,8 +1027,7 @@ private SelectStatement generateSelect(SubselectFetch subselect) {
10241027
rootTableGroup,
10251028
sqlAstCreationState
10261029
)
1027-
),
1028-
singletonList( rootNavigablePath )
1030+
)
10291031
);
10301032
}
10311033

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ public static SelectStatement generateMatchingIdSelectStatement(
124124
sqmConverter
125125
);
126126

127-
return new SelectStatement( idSelectionQuery, domainResults, List.of() );
127+
return new SelectStatement( idSelectionQuery, domainResults );
128128
}
129129

130130
/// Generates a query-spec for selecting all ids matching the restriction defined as part

0 commit comments

Comments
 (0)