HHH-16676 Handle treat expressions in toHqlString

This commit is contained in:
Christian Beikov 2023-05-23 12:51:48 +02:00
parent e79cbe8669
commit 7ed0241dc5
2 changed files with 59 additions and 3 deletions

View File

@ -28,6 +28,7 @@ import org.hibernate.query.sqm.SemanticQueryWalker;
import org.hibernate.query.sqm.tree.SqmCopyContext;
import org.hibernate.query.sqm.tree.SqmNode;
import org.hibernate.query.sqm.tree.domain.SqmEntityValuedSimplePath;
import org.hibernate.query.sqm.tree.domain.SqmTreatedPath;
import org.hibernate.query.sqm.tree.expression.SqmAliasedNodeRef;
import org.hibernate.query.sqm.tree.expression.SqmExpression;
import org.hibernate.query.sqm.tree.from.SqmAttributeJoin;
@ -588,12 +589,14 @@ public class SqmQuerySpec<T> extends SqmQueryPart<T>
sb.append( root.getCorrelationParent().resolveAlias() );
sb.append( ' ' ).append( root.resolveAlias() );
appendJoins( root, sb );
appendTreatJoins( root, sb );
}
}
else {
sb.append( root.getEntityName() );
sb.append( ' ' ).append( root.resolveAlias() );
appendJoins( root, sb );
appendTreatJoins( root, sb );
}
separator = ", ";
}
@ -639,8 +642,16 @@ public class SqmQuerySpec<T> extends SqmQueryPart<T>
}
if ( sqmJoin instanceof SqmAttributeJoin<?, ?> ) {
final SqmAttributeJoin<?, ?> attributeJoin = (SqmAttributeJoin<?, ?>) sqmJoin;
sb.append( sqmFrom.resolveAlias() ).append( '.' );
sb.append( ( attributeJoin ).getAttribute().getName() );
if ( sqmFrom instanceof SqmTreatedPath<?, ?> ) {
final SqmTreatedPath<?, ?> treatedPath = (SqmTreatedPath<?, ?>) sqmFrom;
sb.append( "treat(" );
sb.append( treatedPath.getWrappedPath().resolveAlias() );
sb.append( " as " ).append( treatedPath.getTreatTarget().getName() ).append( ')' );
}
else {
sb.append( sqmFrom.resolveAlias() );
}
sb.append( '.' ).append( ( attributeJoin ).getAttribute().getName() );
sb.append( ' ' ).append( sqmJoin.resolveAlias() );
if ( attributeJoin.getJoinPredicate() != null ) {
sb.append( " on " );
@ -681,4 +692,10 @@ public class SqmQuerySpec<T> extends SqmQueryPart<T>
separator = ", ";
}
}
private void appendTreatJoins(SqmFrom<?, ?> sqmFrom, StringBuilder sb) {
for ( SqmFrom<?, ?> sqmTreat : sqmFrom.getSqmTreats() ) {
appendJoins( sqmTreat, sb );
}
}
}

View File

@ -4,20 +4,32 @@ import org.hibernate.query.spi.SqmQuery;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.orm.junit.EntityManagerFactoryScope;
import org.hibernate.testing.orm.junit.JiraKey;
import org.hibernate.testing.orm.junit.Jpa;
import org.junit.jupiter.api.Test;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.Id;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Query;
import jakarta.persistence.TypedQuery;
import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.CriteriaQuery;
import jakarta.persistence.criteria.Expression;
import jakarta.persistence.criteria.Join;
import jakarta.persistence.criteria.Root;
import org.hamcrest.CoreMatchers;
import org.hamcrest.MatcherAssert;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.MatcherAssert.assertThat;
@Jpa(
annotatedClasses = ToHqlStringTest.TestEntity.class
annotatedClasses = {
ToHqlStringTest.TestEntity.class,
ToHqlStringTest.TestEntitySub.class
}
)
@TestForIssue( jiraKey = "HHH-15389")
public class ToHqlStringTest {
@ -60,6 +72,27 @@ public class ToHqlStringTest {
);
}
@Test
@JiraKey( "HHH-16676" )
public void testCriteriaWithTreatToHqlString(EntityManagerFactoryScope scope) {
scope.inTransaction(
entityManager -> {
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<Object> criteriaQuery = builder.createQuery( Object.class );
Root<TestEntity> root = criteriaQuery.from( TestEntity.class );
Join<Object, Object> entity = builder.treat( root, TestEntitySub.class ).join( "entity" );
criteriaQuery = criteriaQuery.select( entity );
TypedQuery<Object> query = entityManager.createQuery( criteriaQuery );
String hqlString = ( (SqmQuery) query ).getSqmStatement().toHqlString();
final int fromIndex = hqlString.indexOf( " from " );
final String alias = hqlString.substring( "select ".length(), fromIndex );
assertThat( hqlString.substring( fromIndex ), containsString( alias ) );
}
);
}
public static class TestDto {
@Id
public Integer id;
@ -74,4 +107,10 @@ public class ToHqlStringTest {
public String name;
}
@Entity(name = "TestEntitySub")
public static class TestEntitySub extends TestEntity {
@ManyToOne(fetch = FetchType.LAZY)
TestEntity entity;
}
}