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