Skip to content

Commit b159136

Browse files
committed
HHH-19336 - Proper implementation for JPA extended locking scope
HHH-19459 - LockScope, FollowOnLocking
1 parent 0183974 commit b159136

File tree

1 file changed

+41
-29
lines changed

1 file changed

+41
-29
lines changed

hibernate-core/src/main/java/org/hibernate/sql/ast/internal/StandardLockingClauseStrategy.java

Lines changed: 41 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,16 @@ public class StandardLockingClauseStrategy implements LockingClauseStrategy {
4141
private final Locking.Scope lockingScope;
4242
private final int timeout;
4343

44+
/**
45+
* @implNote Tracked separately from {@linkplain #rootsToLock} and
46+
* {@linkplain #joinsToLock} to help answer {@linkplain #containsOuterJoins()}
47+
* for {@linkplain RowLockStrategy#NONE cases} where we otherwise don't need to
48+
* track the tables, allowing to avoid the overhead of the Sets. There is a
49+
* slight trade-off in that we need to inspect the from-elements to make that
50+
* determination when we might otherwise not need to - memory versus cpu.
51+
*/
52+
private boolean queryHasOuterJoins = false;
53+
4454
private Set<TableGroup> rootsToLock;
4555
private Set<TableGroupJoin> joinsToLock;
4656

@@ -61,10 +71,21 @@ public StandardLockingClauseStrategy(
6171

6272
@Override
6373
public void registerRoot(TableGroup root) {
64-
if ( rootsToLock == null ) {
65-
rootsToLock = new HashSet<>();
74+
if ( !queryHasOuterJoins && !dialect.supportsOuterJoinForUpdate() ) {
75+
if ( root.getModelPart() instanceof EntityPersister entityMapping ) {
76+
if ( entityMapping.hasMultipleTables() ) {
77+
// joined inheritance and/or secondary tables - inherently has outer joins
78+
queryHasOuterJoins = true;
79+
}
80+
}
81+
}
82+
83+
if ( rowLockStrategy != RowLockStrategy.NONE ) {
84+
if ( rootsToLock == null ) {
85+
rootsToLock = new HashSet<>();
86+
}
87+
rootsToLock.add( root );
6688
}
67-
rootsToLock.add( root );
6889
}
6990

7091
@Override
@@ -90,41 +111,32 @@ else if ( lockingScope == Locking.Scope.INCLUDE_FETCHES ) {
90111
}
91112

92113
private void trackJoin(TableGroupJoin join) {
93-
if ( joinsToLock == null ) {
94-
joinsToLock = new LinkedHashSet<>();
95-
}
96-
joinsToLock.add( join );
97-
}
98-
99-
@Override
100-
public boolean containsOuterJoins() {
101-
for ( TableGroup tableGroup : rootsToLock ) {
102-
if ( tableGroup.getModelPart() instanceof EntityPersister entityMapping ) {
114+
if ( !queryHasOuterJoins && !dialect.supportsOuterJoinForUpdate() ) {
115+
final TableGroup joinedGroup = join.getJoinedGroup();
116+
if ( join.isInitialized()
117+
&& join.getJoinType() != SqlAstJoinType.INNER
118+
&& !joinedGroup.isVirtual() ) {
119+
queryHasOuterJoins = true;
120+
}
121+
else if ( joinedGroup.getModelPart() instanceof EntityPersister entityMapping ) {
103122
if ( entityMapping.hasMultipleTables() ) {
104123
// joined inheritance and/or secondary tables - inherently has outer joins
105-
return true;
124+
queryHasOuterJoins = true;
106125
}
107126
}
108127
}
109128

110-
if ( joinsToLock != null ) {
111-
for ( TableGroupJoin tableGroupJoin : joinsToLock ) {
112-
final TableGroup joinedGroup = tableGroupJoin.getJoinedGroup();
113-
if ( tableGroupJoin.isInitialized()
114-
&& tableGroupJoin.getJoinType() != SqlAstJoinType.INNER
115-
&& !joinedGroup.isVirtual() ) {
116-
return true;
117-
}
118-
if ( joinedGroup.getModelPart() instanceof EntityPersister entityMapping ) {
119-
if ( entityMapping.hasMultipleTables() ) {
120-
// joined inheritance and/or secondary tables - inherently has outer joins
121-
return true;
122-
}
123-
}
129+
if ( rowLockStrategy != RowLockStrategy.NONE ) {
130+
if ( joinsToLock == null ) {
131+
joinsToLock = new LinkedHashSet<>();
124132
}
133+
joinsToLock.add( join );
125134
}
135+
}
126136

127-
return false;
137+
@Override
138+
public boolean containsOuterJoins() {
139+
return queryHasOuterJoins;
128140
}
129141

130142
@Override

0 commit comments

Comments
 (0)