3434import org .hibernate .metamodel .mapping .JdbcMappingContainer ;
3535import org .hibernate .metamodel .mapping .MappingModelExpressible ;
3636import org .hibernate .metamodel .mapping .ModelPartContainer ;
37+ import org .hibernate .metamodel .mapping .PluralAttributeMapping ;
3738import org .hibernate .metamodel .mapping .SqlTypedMapping ;
39+ import org .hibernate .metamodel .mapping .internal .BasicValuedCollectionPart ;
3840import org .hibernate .metamodel .model .domain .ReturnableType ;
3941import org .hibernate .persister .entity .EntityPersister ;
4042import org .hibernate .persister .internal .SqlFragmentPredicate ;
@@ -5655,7 +5657,7 @@ protected void renderDmlTargetTableGroup(TableGroup tableGroup) {
56555657 assert getStatementStack ().getCurrent () instanceof UpdateStatement updateStatement
56565658 && updateStatement .getTargetTable () == tableGroup .getPrimaryTableReference ();
56575659 appendSql ( getDual () );
5658- renderTableReferenceJoins ( tableGroup );
5660+ renderTableReferenceJoins ( tableGroup , LockMode . NONE );
56595661 processNestedTableGroupJoins ( tableGroup , null );
56605662 processTableGroupJoins ( tableGroup );
56615663 if ( tableGroup .getModelPart () instanceof EntityPersister persister ) {
@@ -5697,7 +5699,8 @@ protected void renderRootTableGroup(TableGroup tableGroup, List<TableGroupJoin>
56975699 addAdditionalWherePredicate ( determineLateralEmulationPredicate ( tableGroup ) );
56985700 }
56995701
5700- renderTableReferenceJoins ( tableGroup );
5702+ final LockMode lockMode = getEffectiveLockMode ();
5703+ renderTableReferenceJoins ( tableGroup , lockMode );
57015704 processNestedTableGroupJoins ( tableGroup , tableGroupJoinCollector );
57025705 if ( tableGroupJoinCollector != null ) {
57035706 tableGroupJoinCollector .addAll ( tableGroup .getTableGroupJoins () );
@@ -5713,7 +5716,14 @@ protected void renderRootTableGroup(TableGroup tableGroup, List<TableGroupJoin>
57135716 }
57145717 }
57155718
5716- protected void renderTableGroup (TableGroup tableGroup , Predicate predicate , List <TableGroupJoin > tableGroupJoinCollector ) {
5719+ /**
5720+ * Called to render the joined TableGroup from a {@linkplain TableGroupJoin}
5721+ * @param tableGroup The joined TableGroup
5722+ * @param tableGroupJoinCollector Collector for any nested TableGroupJoins
5723+ */
5724+ protected void renderJoinedTableGroup (TableGroup tableGroup , Predicate predicate , List <TableGroupJoin > tableGroupJoinCollector ) {
5725+ final LockMode lockModeToApply = determineJoinedTableGroupLockMode ( tableGroup );
5726+
57175727 final boolean realTableGroup ;
57185728 int swappedJoinIndex = -1 ;
57195729 boolean forceLeftJoin = false ;
@@ -5746,7 +5756,7 @@ else if ( referenceJoinIndexForPredicateSwap == TableGroupHelper.NO_TABLE_GROUP_
57465756
57475757 // Render the table reference of the table reference join first
57485758 final TableReferenceJoin tableReferenceJoin = tableGroup .getTableReferenceJoins ().get ( swappedJoinIndex );
5749- renderNamedTableReference ( tableReferenceJoin .getJoinedTableReference (), LockMode . NONE );
5759+ renderNamedTableReference ( tableReferenceJoin .getJoinedTableReference (), lockModeToApply );
57505760 // along with the predicate for the table group
57515761 if ( predicate != null ) {
57525762 appendSql ( " on " );
@@ -5772,15 +5782,14 @@ else if ( referenceJoinIndexForPredicateSwap == TableGroupHelper.NO_TABLE_GROUP_
57725782 appendSql ( OPEN_PARENTHESIS );
57735783 }
57745784
5775- final LockMode effectiveLockMode = getEffectiveLockMode ( tableGroup .getSourceAlias () );
5776- final boolean usesLockHint = renderPrimaryTableReference ( tableGroup , effectiveLockMode );
5785+ renderPrimaryTableReference ( tableGroup , lockModeToApply );
57775786 final List <TableGroupJoin > tableGroupJoins ;
57785787
57795788 if ( realTableGroup ) {
57805789 // For real table groups, we collect all normal table group joins within that table group
57815790 // The purpose of that is to render them in-order outside of the group/parenthesis
57825791 // This is necessary for at least Derby but is also a lot easier to read
5783- renderTableReferenceJoins ( tableGroup );
5792+ renderTableReferenceJoins ( tableGroup , lockModeToApply );
57845793 if ( tableGroupJoinCollector == null ) {
57855794 tableGroupJoins = new ArrayList <>();
57865795 processNestedTableGroupJoins ( tableGroup , tableGroupJoins );
@@ -5814,7 +5823,7 @@ else if ( referenceJoinIndexForPredicateSwap == TableGroupHelper.NO_TABLE_GROUP_
58145823 }
58155824
58165825 if ( !realTableGroup ) {
5817- renderTableReferenceJoins ( tableGroup , swappedJoinIndex , forceLeftJoin );
5826+ renderTableReferenceJoins ( tableGroup , lockModeToApply , swappedJoinIndex , forceLeftJoin );
58185827 processNestedTableGroupJoins ( tableGroup , tableGroupJoinCollector );
58195828 }
58205829 if ( tableGroupJoinCollector != null ) {
@@ -5838,6 +5847,32 @@ else if ( referenceJoinIndexForPredicateSwap == TableGroupHelper.NO_TABLE_GROUP_
58385847 }
58395848 }
58405849
5850+ private LockMode determineJoinedTableGroupLockMode (TableGroup joinedTableGroup ) {
5851+ final Locking .Scope lockingScope = lockOptions == null ? Locking .Scope .ROOT_ONLY : lockOptions .getScope ();
5852+
5853+ if ( lockingScope == Locking .Scope .ROOT_ONLY ) {
5854+ return LockMode .NONE ;
5855+ }
5856+
5857+ if ( lockingScope == Locking .Scope .INCLUDE_FETCHES ) {
5858+ return joinedTableGroup .isFetched () ? getEffectiveLockMode () : LockMode .NONE ;
5859+ }
5860+
5861+ if ( lockingScope == Locking .Scope .INCLUDE_COLLECTIONS ) {
5862+ // if the TableGroup is an owned (aka, non-inverse) collection, lock it
5863+ if ( joinedTableGroup .getModelPart () instanceof PluralAttributeMapping attrMapping ) {
5864+ if ( !attrMapping .getCollectionDescriptor ().isInverse () ) {
5865+ // owned collection
5866+ if ( attrMapping .getElementDescriptor () instanceof BasicValuedCollectionPart ) {
5867+ return getEffectiveLockMode ();
5868+ }
5869+ }
5870+ }
5871+ }
5872+
5873+ return LockMode .NONE ;
5874+ }
5875+
58415876 protected boolean needsLocking (QuerySpec querySpec ) {
58425877 return querySpec .getFromClause ().queryTableGroups (
58435878 tableGroup -> {
@@ -6122,11 +6157,11 @@ protected void registerAffectedTable(String tableExpression) {
61226157 affectedTableNames .add ( tableExpression );
61236158 }
61246159
6125- protected void renderTableReferenceJoins (TableGroup tableGroup ) {
6126- renderTableReferenceJoins ( tableGroup , -1 , false );
6160+ protected void renderTableReferenceJoins (TableGroup tableGroup , LockMode lockMode ) {
6161+ renderTableReferenceJoins ( tableGroup , lockMode , -1 , false );
61276162 }
61286163
6129- protected void renderTableReferenceJoins (TableGroup tableGroup , int swappedJoinIndex , boolean forceLeftJoin ) {
6164+ protected void renderTableReferenceJoins (TableGroup tableGroup , LockMode lockMode , int swappedJoinIndex , boolean forceLeftJoin ) {
61306165 final List <TableReferenceJoin > joins = tableGroup .getTableReferenceJoins ();
61316166 if ( joins == null || joins .isEmpty () ) {
61326167 return ;
@@ -6154,7 +6189,7 @@ protected void renderTableReferenceJoins(TableGroup tableGroup, int swappedJoinI
61546189 }
61556190 appendSql ( "join " );
61566191
6157- renderNamedTableReference ( tableJoin .getJoinedTableReference (), LockMode . NONE );
6192+ renderNamedTableReference ( tableJoin .getJoinedTableReference (), lockMode );
61586193
61596194 if ( tableJoin .getPredicate () != null && !tableJoin .getPredicate ().isEmpty () ) {
61606195 appendSql ( " on " );
@@ -6220,10 +6255,10 @@ protected void renderTableGroupJoin(TableGroupJoin tableGroupJoin, List<TableGro
62206255 predicate = tableGroupJoin .getPredicate ();
62216256 }
62226257 if ( predicate != null && !predicate .isEmpty () ) {
6223- renderTableGroup ( tableGroupJoin .getJoinedGroup (), predicate , tableGroupJoinCollector );
6258+ renderJoinedTableGroup ( tableGroupJoin .getJoinedGroup (), predicate , tableGroupJoinCollector );
62246259 }
62256260 else {
6226- renderTableGroup ( tableGroupJoin .getJoinedGroup (), null , tableGroupJoinCollector );
6261+ renderJoinedTableGroup ( tableGroupJoin .getJoinedGroup (), null , tableGroupJoinCollector );
62276262 }
62286263 if ( lockingClauseStrategy != null ) {
62296264 lockingClauseStrategy .registerJoin ( tableGroupJoin );
0 commit comments