Skip to content

Commit bd33ff8

Browse files
committed
HHH-19551 - Address deficiencies in pessimistic locking
1 parent dcd837c commit bd33ff8

File tree

10 files changed

+119
-55
lines changed

10 files changed

+119
-55
lines changed

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
import org.hibernate.dialect.OracleDialect;
2020
import org.hibernate.dialect.function.CommonFunctionFactory;
2121
import org.hibernate.dialect.function.OracleTruncFunction;
22-
import org.hibernate.dialect.lock.internal.NoLockingSupport;
22+
import org.hibernate.dialect.lock.internal.LockingSupportSimple;
2323
import org.hibernate.dialect.lock.spi.LockingSupport;
2424
import org.hibernate.dialect.pagination.LimitHandler;
2525
import org.hibernate.dialect.sequence.SequenceSupport;
@@ -587,7 +587,7 @@ public boolean supportsFromClauseInUpdate() {
587587

588588
@Override
589589
public LockingSupport getLockingSupport() {
590-
return NoLockingSupport.NO_LOCKING_SUPPORT;
590+
return LockingSupportSimple.NO_OUTER_JOIN;
591591
}
592592

593593
@Override

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import org.hibernate.community.dialect.pagination.DerbyLimitHandler;
1515
import org.hibernate.community.dialect.sequence.DerbySequenceSupport;
1616
import org.hibernate.community.dialect.sequence.SequenceInformationExtractorDerbyDatabaseImpl;
17+
import org.hibernate.community.dialect.temptable.DerbyLocalTemporaryTableStrategy;
1718
import org.hibernate.dialect.DB2Dialect;
1819
import org.hibernate.dialect.DatabaseVersion;
1920
import org.hibernate.dialect.Dialect;
@@ -28,11 +29,10 @@
2829
import org.hibernate.dialect.function.InsertSubstringOverlayEmulation;
2930
import org.hibernate.dialect.identity.DB2IdentityColumnSupport;
3031
import org.hibernate.dialect.identity.IdentityColumnSupport;
31-
import org.hibernate.dialect.lock.internal.NoLockingSupport;
32+
import org.hibernate.dialect.lock.internal.LockingSupportSimple;
3233
import org.hibernate.dialect.lock.spi.LockingSupport;
3334
import org.hibernate.dialect.pagination.LimitHandler;
3435
import org.hibernate.dialect.sequence.SequenceSupport;
35-
import org.hibernate.community.dialect.temptable.DerbyLocalTemporaryTableStrategy;
3636
import org.hibernate.dialect.temptable.TemporaryTableKind;
3737
import org.hibernate.dialect.temptable.TemporaryTableStrategy;
3838
import org.hibernate.dialect.unique.CreateTableUniqueDelegate;
@@ -53,9 +53,9 @@
5353
import org.hibernate.query.common.TemporalUnit;
5454
import org.hibernate.query.sqm.CastType;
5555
import org.hibernate.query.sqm.IntervalType;
56-
import org.hibernate.query.sqm.mutation.spi.BeforeUseAction;
5756
import org.hibernate.query.sqm.mutation.internal.temptable.LocalTemporaryTableInsertStrategy;
5857
import org.hibernate.query.sqm.mutation.internal.temptable.LocalTemporaryTableMutationStrategy;
58+
import org.hibernate.query.sqm.mutation.spi.BeforeUseAction;
5959
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableInsertStrategy;
6060
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
6161
import org.hibernate.service.ServiceRegistry;
@@ -577,7 +577,7 @@ public boolean supportsCommentOn() {
577577

578578
@Override
579579
public LockingSupport getLockingSupport() {
580-
return NoLockingSupport.NO_LOCKING_SUPPORT;
580+
return LockingSupportSimple.NO_OUTER_JOIN;
581581
}
582582

583583
@Override

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import org.hibernate.community.dialect.pagination.DerbyLimitHandler;
1515
import org.hibernate.community.dialect.sequence.DerbySequenceSupport;
1616
import org.hibernate.community.dialect.sequence.SequenceInformationExtractorDerbyDatabaseImpl;
17+
import org.hibernate.community.dialect.temptable.DerbyLocalTemporaryTableStrategy;
1718
import org.hibernate.dialect.DB2Dialect;
1819
import org.hibernate.dialect.DatabaseVersion;
1920
import org.hibernate.dialect.Dialect;
@@ -28,12 +29,11 @@
2829
import org.hibernate.dialect.function.InsertSubstringOverlayEmulation;
2930
import org.hibernate.dialect.identity.DB2IdentityColumnSupport;
3031
import org.hibernate.dialect.identity.IdentityColumnSupport;
31-
import org.hibernate.dialect.lock.internal.NoLockingSupport;
32+
import org.hibernate.dialect.lock.internal.LockingSupportSimple;
3233
import org.hibernate.dialect.lock.spi.LockingSupport;
3334
import org.hibernate.dialect.pagination.AbstractLimitHandler;
3435
import org.hibernate.dialect.pagination.LimitHandler;
3536
import org.hibernate.dialect.sequence.SequenceSupport;
36-
import org.hibernate.community.dialect.temptable.DerbyLocalTemporaryTableStrategy;
3737
import org.hibernate.dialect.temptable.TemporaryTableKind;
3838
import org.hibernate.dialect.temptable.TemporaryTableStrategy;
3939
import org.hibernate.engine.jdbc.Size;
@@ -52,9 +52,9 @@
5252
import org.hibernate.query.common.TemporalUnit;
5353
import org.hibernate.query.sqm.CastType;
5454
import org.hibernate.query.sqm.IntervalType;
55-
import org.hibernate.query.sqm.mutation.spi.BeforeUseAction;
5655
import org.hibernate.query.sqm.mutation.internal.temptable.LocalTemporaryTableInsertStrategy;
5756
import org.hibernate.query.sqm.mutation.internal.temptable.LocalTemporaryTableMutationStrategy;
57+
import org.hibernate.query.sqm.mutation.spi.BeforeUseAction;
5858
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableInsertStrategy;
5959
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
6060
import org.hibernate.service.ServiceRegistry;
@@ -618,7 +618,7 @@ public String getReadLockString(int timeout) {
618618

619619
@Override
620620
public LockingSupport getLockingSupport() {
621-
return NoLockingSupport.NO_LOCKING_SUPPORT;
621+
return LockingSupportSimple.NO_OUTER_JOIN;
622622
}
623623

624624
@Override

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

Lines changed: 23 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,7 @@
44
*/
55
package org.hibernate.community.dialect;
66

7-
import java.sql.DatabaseMetaData;
8-
import java.sql.SQLException;
9-
import java.sql.Types;
10-
import java.time.Instant;
11-
import java.time.format.DateTimeFormatter;
12-
import java.time.format.DateTimeFormatterBuilder;
13-
import java.time.temporal.ChronoField;
14-
import java.time.temporal.TemporalAccessor;
15-
import java.util.Arrays;
16-
import java.util.Calendar;
17-
import java.util.Date;
18-
import java.util.Locale;
19-
import java.util.TimeZone;
20-
import java.util.UUID;
21-
import java.util.regex.Matcher;
22-
import java.util.regex.Pattern;
23-
7+
import jakarta.persistence.TemporalType;
248
import org.hibernate.boot.Metadata;
259
import org.hibernate.boot.model.FunctionContributions;
2610
import org.hibernate.boot.model.TypeContributions;
@@ -35,11 +19,12 @@
3519
import org.hibernate.dialect.Dialect;
3620
import org.hibernate.dialect.DmlTargetColumnQualifierSupport;
3721
import org.hibernate.dialect.NationalizationSupport;
22+
import org.hibernate.dialect.NullOrdering;
3823
import org.hibernate.dialect.TimeZoneSupport;
3924
import org.hibernate.dialect.function.CommonFunctionFactory;
4025
import org.hibernate.dialect.function.HypotheticalSetWindowEmulation;
4126
import org.hibernate.dialect.identity.IdentityColumnSupport;
42-
import org.hibernate.dialect.lock.internal.NoLockingSupport;
27+
import org.hibernate.dialect.lock.internal.LockingSupportSimple;
4328
import org.hibernate.dialect.lock.spi.LockingSupport;
4429
import org.hibernate.dialect.pagination.LimitHandler;
4530
import org.hibernate.dialect.pagination.OffsetFetchLimitHandler;
@@ -61,11 +46,10 @@
6146
import org.hibernate.mapping.Index;
6247
import org.hibernate.metamodel.mapping.EntityMappingType;
6348
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
64-
import org.hibernate.query.sqm.CastType;
6549
import org.hibernate.query.common.FetchClauseType;
66-
import org.hibernate.query.sqm.IntervalType;
67-
import org.hibernate.dialect.NullOrdering;
6850
import org.hibernate.query.common.TemporalUnit;
51+
import org.hibernate.query.sqm.CastType;
52+
import org.hibernate.query.sqm.IntervalType;
6953
import org.hibernate.query.sqm.function.SqmFunctionRegistry;
7054
import org.hibernate.query.sqm.mutation.internal.temptable.GlobalTemporaryTableInsertStrategy;
7155
import org.hibernate.query.sqm.mutation.internal.temptable.GlobalTemporaryTableMutationStrategy;
@@ -91,10 +75,25 @@
9175
import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry;
9276
import org.hibernate.type.descriptor.sql.internal.BinaryFloatDdlType;
9377
import org.hibernate.type.descriptor.sql.spi.DdlTypeRegistry;
94-
95-
import jakarta.persistence.TemporalType;
9678
import org.hibernate.type.spi.TypeConfiguration;
9779

80+
import java.sql.DatabaseMetaData;
81+
import java.sql.SQLException;
82+
import java.sql.Types;
83+
import java.time.Instant;
84+
import java.time.format.DateTimeFormatter;
85+
import java.time.format.DateTimeFormatterBuilder;
86+
import java.time.temporal.ChronoField;
87+
import java.time.temporal.TemporalAccessor;
88+
import java.util.Arrays;
89+
import java.util.Calendar;
90+
import java.util.Date;
91+
import java.util.Locale;
92+
import java.util.TimeZone;
93+
import java.util.UUID;
94+
import java.util.regex.Matcher;
95+
import java.util.regex.Pattern;
96+
9897
import static org.hibernate.query.sqm.produce.function.FunctionParameterType.INTEGER;
9998
import static org.hibernate.query.sqm.produce.function.FunctionParameterType.STRING;
10099
import static org.hibernate.type.SqlTypes.BINARY;
@@ -726,7 +725,7 @@ public String getSelectGUIDString() {
726725

727726
@Override
728727
public LockingSupport getLockingSupport() {
729-
return NoLockingSupport.NO_LOCKING_SUPPORT;
728+
return LockingSupportSimple.NO_OUTER_JOIN;
730729
}
731730

732731
@Override

hibernate-core/src/main/java/org/hibernate/Locking.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
*
2121
* @author Steve Ebersole
2222
*/
23+
@Incubating
2324
public interface Locking {
2425
/**
2526
* When pessimistic locking is requested, this enum defines

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@
4747
import java.util.Locale;
4848

4949
/**
50+
* LockingStrategy implementation which uses Hibernate's SQL AST
51+
* mechanism for applying pessimistic locks.
52+
*
5053
* @author Steve Ebersole
5154
*/
5255
public class SqlAstBasedLockingStrategy implements LockingStrategy {

hibernate-core/src/main/java/org/hibernate/dialect/lock/package-info.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,10 @@
77
* Support for {@link org.hibernate.dialect.Dialect}-specific locking strategies.
88
*
99
* @see org.hibernate.dialect.lock.LockingStrategy
10+
*
11+
* @apiNote Marked incubating as major refactoring and reorganizing expected here during 7.x development.
1012
*/
13+
@Incubating
1114
package org.hibernate.dialect.lock;
15+
16+
import org.hibernate.Incubating;

hibernate-core/src/main/java/org/hibernate/dialect/lock/spi/LockTimeoutType.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,23 @@
55
package org.hibernate.dialect.lock.spi;
66

77
/**
8+
* The way, if any, that a Dialect supports specifying lock timeouts.
9+
*
810
* @author Steve Ebersole
911
*/
1012
public enum LockTimeoutType {
13+
/**
14+
* Lock timeouts are simply not supported.
15+
*/
1116
NONE,
17+
/**
18+
* Lock timeouts are supported as part of the query; e.g. {@code for update ... wait 1000}.
19+
*/
1220
QUERY,
21+
/**
22+
* Lock timeouts are supported on the JDBC Connection, typically through an {@code alter session} command.
23+
*
24+
* @see ConnectionLockTimeoutStrategy
25+
*/
1326
CONNECTION
1427
}

hibernate-testing/src/main/java/org/hibernate/testing/orm/AsyncExecutor.java

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -14,31 +14,33 @@
1414
*/
1515
public class AsyncExecutor {
1616
public static void executeAsync(Runnable action) {
17-
final ExecutorService executorService = Executors.newSingleThreadExecutor();
18-
try {
19-
executorService.submit( action ).get();
20-
}
21-
catch (InterruptedException e) {
22-
throw new RuntimeException( "Thread interruption", e );
23-
}
24-
catch (ExecutionException e) {
25-
throw new RuntimeException( "Async execution error", e );
17+
try (ExecutorService executorService = Executors.newSingleThreadExecutor()) {
18+
try {
19+
executorService.submit( action ).get();
20+
}
21+
catch (InterruptedException e) {
22+
throw new RuntimeException( "Thread interruption", e );
23+
}
24+
catch (ExecutionException e) {
25+
throw new RuntimeException( "Async execution error", e );
26+
}
2627
}
2728
}
2829

2930
public static void executeAsync(int timeout, TimeUnit timeoutUnit, Runnable action) {
30-
final ExecutorService executorService = Executors.newSingleThreadExecutor();
31-
try {
32-
executorService.submit( action ).get( timeout, timeoutUnit );
33-
}
34-
catch (InterruptedException e) {
35-
throw new TimeoutException( "Thread interruption", e );
36-
}
37-
catch (java.util.concurrent.TimeoutException e) {
38-
throw new TimeoutException( "Thread timeout exceeded", e );
39-
}
40-
catch (ExecutionException e) {
41-
throw new RuntimeException( "Async execution error", e.getCause() );
31+
try (ExecutorService executorService = Executors.newSingleThreadExecutor()) {
32+
try {
33+
executorService.submit( action ).get( timeout, timeoutUnit );
34+
}
35+
catch (InterruptedException e) {
36+
throw new TimeoutException( "Thread interruption", e );
37+
}
38+
catch (java.util.concurrent.TimeoutException e) {
39+
throw new TimeoutException( "Thread timeout exceeded", e );
40+
}
41+
catch (ExecutionException e) {
42+
throw new RuntimeException( "Async execution error", e.getCause() );
43+
}
4244
}
4345
}
4446

migration-guide.adoc

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,47 @@ earlier versions, see any other pertinent migration guides as well.
2121

2222
This section describes changes to contracts (classes, interfaces, methods, etc.) which are considered https://hibernate.org/community/compatibility-policy/#api[API].
2323

24+
[[lock-options]]
25+
=== LockOptions
26+
27+
7.0 begins the process of reducing the visibility of `org.hibernate.LockOptions`.
28+
This class was originally exposed as an API, even though it is more properly an SPI.
29+
From an API perspective, `FindOption`, `LockOption` and `RefreshOption` are much better ways to specify that information.
30+
The class itself, as well as API methods which expose it, have been deprecated.
31+
32+
However, 2 aspects of `LockOptions` have been completely removed.
33+
First, `LockOptions` previously defined a number of constants which have been removed.
34+
Secondly, the ability to define different LockModes for individual aliases has been removed.
35+
36+
[NOTE]
37+
----
38+
ALias-specific LockModes was a very misleading feature, as Hibernate would only ever use the "greatest" LockMode.
39+
We plan to add the ability to specify a list of aliases to be locked in a later release.
40+
See https://hibernate.atlassian.net/browse/HHH-19664 for details.
41+
----
42+
43+
Application code using `org.hibernate.LockOptions` should migrate to using `FindOption`,
44+
`LockOption` and `RefreshOption` to control the various aspects of locking. E.g.
45+
46+
[source,java]
47+
----
48+
LockOptions lockOptions = new LockOptions();
49+
lockOptions.setLockMode(PESSIMISTIC_WRITE);
50+
lockOptions.setTimeout(1000);
51+
session.refresh(book, lockOptions);
52+
----
53+
54+
can instead be written as
55+
56+
[source,java]
57+
----
58+
session.refresh(book,
59+
PESSIMISTIC_WRITE,
60+
Timeout.milliseconds(1000));
61+
----
62+
63+
64+
2465
[[session-getLobHelper]]
2566
=== Session#getLobHelper
2667

0 commit comments

Comments
 (0)