HHH-17143 - More not-found fix ups
https://hibernate.atlassian.net/browse/HHH-17143
This commit is contained in:
parent
f7709e7610
commit
3e96ddce40
|
@ -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,
|
||||||
|
|
|
@ -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 ) {
|
||||||
|
|
|
@ -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 ) {
|
|
||||||
joinType = getDefaultSqlAstJoinType( lhs );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
joinType = SqlAstJoinType.INNER;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
joinType = requestedJoinType;
|
if ( fetched ) {
|
||||||
|
return getDefaultSqlAstJoinType( lhs );
|
||||||
}
|
}
|
||||||
return joinType;
|
|
||||||
|
return SqlAstJoinType.INNER;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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" );
|
||||||
|
} );
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue