HHH-17143 - More not-found fix ups

https://hibernate.atlassian.net/browse/HHH-17143
This commit is contained in:
Steve Ebersole 2023-08-31 08:27:15 -05:00 committed by Christian Beikov
parent f7709e7610
commit 3e96ddce40
4 changed files with 41 additions and 17 deletions

View File

@ -63,6 +63,7 @@ import org.hibernate.property.access.spi.PropertyAccess;
import org.hibernate.spi.EntityIdentifierNavigablePath; import org.hibernate.spi.EntityIdentifierNavigablePath;
import org.hibernate.spi.NavigablePath; import org.hibernate.spi.NavigablePath;
import org.hibernate.spi.TreatedNavigablePath; import org.hibernate.spi.TreatedNavigablePath;
import org.hibernate.sql.ast.Clause;
import org.hibernate.sql.ast.SqlAstJoinType; import org.hibernate.sql.ast.SqlAstJoinType;
import org.hibernate.sql.ast.spi.FromClauseAccess; import org.hibernate.sql.ast.spi.FromClauseAccess;
import org.hibernate.sql.ast.spi.SqlAliasBase; import org.hibernate.sql.ast.spi.SqlAliasBase;
@ -1991,6 +1992,19 @@ public class ToOneAttributeMapping
return join; return join;
} }
@Override
public SqlAstJoinType determineSqlJoinType(TableGroup lhs, SqlAstJoinType requestedJoinType, boolean fetched) {
if ( requestedJoinType != null ) {
return requestedJoinType;
}
if ( fetched ) {
return getDefaultSqlAstJoinType( lhs );
}
return SqlAstJoinType.INNER;
}
@Override @Override
public LazyTableGroup createRootTableGroupJoin( public LazyTableGroup createRootTableGroupJoin(
NavigablePath navigablePath, NavigablePath navigablePath,

View File

@ -206,10 +206,11 @@ public class EntityValuedPathInterpretation<T> extends AbstractSqmPathInterpreta
resultTableGroup = tableGroup; resultTableGroup = tableGroup;
} }
} }
else if ( inferredMapping == null && hasNotFound( mapping ) ) { else if ( inferredMapping == null
// This is necessary to allow expression like `where root.notFoundAssociation is null` && hasNotFound( mapping )
// to render to `alias.not_found_fk is null`, but IMO this shouldn't be done && sqlAstCreationState.getCurrentClauseStack().getCurrent() == Clause.SET ) {
// todo: discuss removing this part and create a left joined table group instead? // for not-found mappings encountered in the SET clause of an UPDATE statement
// we will want to (1) not join and (2) render the fk
resultModelPart = keyTargetMatchPart; resultModelPart = keyTargetMatchPart;
resultTableGroup = sqlAstCreationState.getFromClauseAccess() resultTableGroup = sqlAstCreationState.getFromClauseAccess()
.findTableGroup( tableGroup.getNavigablePath().getParent() ); .findTableGroup( tableGroup.getNavigablePath().getParent() );
@ -218,6 +219,10 @@ public class EntityValuedPathInterpretation<T> extends AbstractSqmPathInterpreta
// If the mapping is an inverse association, use the PK and disallow FK optimizations // If the mapping is an inverse association, use the PK and disallow FK optimizations
resultModelPart = ( (EntityAssociationMapping) mapping ).getAssociatedEntityMappingType().getIdentifierMapping(); resultModelPart = ( (EntityAssociationMapping) mapping ).getAssociatedEntityMappingType().getIdentifierMapping();
resultTableGroup = tableGroup; resultTableGroup = tableGroup;
// todo (not-found) : in the case of not-found=ignore, we want to do the join, however -
// * use a left join when the association is the path terminus (`root.association`)
// * use an inner join when it is further de-referenced (`root.association.stuff`)
} }
} }
else if ( mapping instanceof AnonymousTupleEntityValuedModelPart ) { else if ( mapping instanceof AnonymousTupleEntityValuedModelPart ) {

View File

@ -78,18 +78,14 @@ public interface TableGroupJoinProducer extends TableGroupProducer {
SqlAstCreationState creationState); SqlAstCreationState creationState);
default SqlAstJoinType determineSqlJoinType(TableGroup lhs, SqlAstJoinType requestedJoinType, boolean fetched) { default SqlAstJoinType determineSqlJoinType(TableGroup lhs, SqlAstJoinType requestedJoinType, boolean fetched) {
final SqlAstJoinType joinType; if ( requestedJoinType != null ) {
if ( requestedJoinType == null ) { return requestedJoinType;
}
if ( fetched ) { if ( fetched ) {
joinType = getDefaultSqlAstJoinType( lhs ); return getDefaultSqlAstJoinType( lhs );
} }
else {
joinType = SqlAstJoinType.INNER; return SqlAstJoinType.INNER;
}
}
else {
joinType = requestedJoinType;
}
return joinType;
} }
} }

View File

@ -3,6 +3,7 @@ package org.hibernate.orm.test.notfound;
import org.hibernate.annotations.NotFound; import org.hibernate.annotations.NotFound;
import org.hibernate.annotations.NotFoundAction; import org.hibernate.annotations.NotFoundAction;
import org.hibernate.testing.jdbc.SQLStatementInspector;
import org.hibernate.testing.orm.junit.DomainModel; import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.JiraKey; import org.hibernate.testing.orm.junit.JiraKey;
import org.hibernate.testing.orm.junit.SessionFactory; import org.hibernate.testing.orm.junit.SessionFactory;
@ -17,7 +18,7 @@ import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne; import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table; import jakarta.persistence.Table;
import static org.assertj.core.api.AssertionsForClassTypes.assertThat; import static org.assertj.core.api.Assertions.assertThat;
@DomainModel( @DomainModel(
annotatedClasses = { annotatedClasses = {
@ -25,7 +26,7 @@ import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
MutationQueriesAndNotFoundActionTest.Comment.class MutationQueriesAndNotFoundActionTest.Comment.class
} }
) )
@SessionFactory @SessionFactory( useCollectingStatementInspector = true )
@JiraKey("HHH-16878") @JiraKey("HHH-16878")
public class MutationQueriesAndNotFoundActionTest { public class MutationQueriesAndNotFoundActionTest {
@ -56,8 +57,12 @@ public class MutationQueriesAndNotFoundActionTest {
@Test @Test
public void testUpdate(SessionFactoryScope scope) { public void testUpdate(SessionFactoryScope scope) {
final SQLStatementInspector statementInspector = scope.getCollectingStatementInspector();
scope.inTransaction( scope.inTransaction(
session -> { session -> {
statementInspector.clear();
int affectedComments = session.createMutationQuery( int affectedComments = session.createMutationQuery(
"update Comment c set c.text = :text where c.user = :user" ) "update Comment c set c.text = :text where c.user = :user" )
.setParameter( "text", "updated" ) .setParameter( "text", "updated" )
@ -65,6 +70,10 @@ public class MutationQueriesAndNotFoundActionTest {
.executeUpdate(); .executeUpdate();
assertThat( affectedComments ).isEqualTo( 2 ); assertThat( affectedComments ).isEqualTo( 2 );
assertThat( statementInspector.getSqlQueries() ).hasSize( 1 );
assertThat( statementInspector.getSqlQueries().get( 0 ) ).matches( (sql) -> {
return sql.contains( " join " ) || sql.contains( "exists" );
} );
} }
); );
} }