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.NavigablePath;
import org.hibernate.spi.TreatedNavigablePath;
import org.hibernate.sql.ast.Clause;
import org.hibernate.sql.ast.SqlAstJoinType;
import org.hibernate.sql.ast.spi.FromClauseAccess;
import org.hibernate.sql.ast.spi.SqlAliasBase;
@ -1991,6 +1992,19 @@ public class ToOneAttributeMapping
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
public LazyTableGroup createRootTableGroupJoin(
NavigablePath navigablePath,

View File

@ -206,10 +206,11 @@ public class EntityValuedPathInterpretation<T> extends AbstractSqmPathInterpreta
resultTableGroup = tableGroup;
}
}
else if ( inferredMapping == null && hasNotFound( mapping ) ) {
// This is necessary to allow expression like `where root.notFoundAssociation is null`
// to render to `alias.not_found_fk is null`, but IMO this shouldn't be done
// todo: discuss removing this part and create a left joined table group instead?
else if ( inferredMapping == null
&& hasNotFound( mapping )
&& sqlAstCreationState.getCurrentClauseStack().getCurrent() == Clause.SET ) {
// 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;
resultTableGroup = sqlAstCreationState.getFromClauseAccess()
.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
resultModelPart = ( (EntityAssociationMapping) mapping ).getAssociatedEntityMappingType().getIdentifierMapping();
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 ) {

View File

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

View File

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