HHH-16483 Add test for issue
This commit is contained in:
parent
8bd99231a5
commit
5578109fe7
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||
*/
|
||||
package org.hibernate.orm.test.jpa.compliance;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.query.criteria.HibernateCriteriaBuilder;
|
||||
import org.hibernate.query.criteria.JpaCriteriaQuery;
|
||||
import org.hibernate.query.criteria.JpaCteCriteria;
|
||||
import org.hibernate.query.criteria.JpaRoot;
|
||||
import org.hibernate.query.hql.spi.SqmQueryImplementor;
|
||||
|
||||
import org.hibernate.testing.orm.junit.DialectFeatureChecks;
|
||||
import org.hibernate.testing.orm.junit.EntityManagerFactoryScope;
|
||||
import org.hibernate.testing.orm.junit.Jira;
|
||||
import org.hibernate.testing.orm.junit.Jpa;
|
||||
import org.hibernate.testing.orm.junit.RequiresDialectFeature;
|
||||
import org.hibernate.testing.orm.junit.Setting;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.OneToOne;
|
||||
import jakarta.persistence.Tuple;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* @author Marco Belladelli
|
||||
*/
|
||||
@Jpa(
|
||||
annotatedClasses = CriteriaRecursiveCteCopyTest.Account.class,
|
||||
properties = @Setting( name = AvailableSettings.CRITERIA_COPY_TREE, value = "true" )
|
||||
)
|
||||
@RequiresDialectFeature( feature = DialectFeatureChecks.SupportsRecursiveCtes.class )
|
||||
@Jira( "https://hibernate.atlassian.net/browse/HHH-16483" )
|
||||
public class CriteriaRecursiveCteCopyTest {
|
||||
@BeforeAll
|
||||
public void setUp(EntityManagerFactoryScope scope) {
|
||||
scope.inTransaction( entityManager -> {
|
||||
final Account parent = new Account( "Parent Account", null );
|
||||
final Account child = new Account( "Child Account", parent );
|
||||
entityManager.persist( parent );
|
||||
entityManager.persist( child );
|
||||
} );
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
public void tearDown(EntityManagerFactoryScope scope) {
|
||||
scope.inTransaction( entityManager -> {
|
||||
entityManager.createQuery( "delete from Account a where a.parent is not null" ).executeUpdate();
|
||||
entityManager.createQuery( "delete from Account" ).executeUpdate();
|
||||
} );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRecursiveCte(EntityManagerFactoryScope scope) {
|
||||
scope.inTransaction( entityManager -> {
|
||||
final HibernateCriteriaBuilder builder = (HibernateCriteriaBuilder) entityManager.getCriteriaBuilder();
|
||||
final JpaCriteriaQuery<Tuple> query = builder.createTupleQuery();
|
||||
final JpaCriteriaQuery<Tuple> nonRecurQuery = builder.createTupleQuery();
|
||||
final JpaRoot<Account> nonRecurRoot = nonRecurQuery.from( Account.class );
|
||||
nonRecurQuery.multiselect(
|
||||
nonRecurRoot.get( "id" ).alias( "id" ),
|
||||
nonRecurRoot.get( "name" ).alias( "name" ),
|
||||
nonRecurRoot.get( "parent" ).get( "id" ).alias( "parent_id" )
|
||||
);
|
||||
nonRecurQuery.where( builder.like( builder.lower( nonRecurRoot.get( "name" ) ), "%child%" ) );
|
||||
final JpaCteCriteria<Tuple> accountChainTable = query.withRecursiveUnionAll( nonRecurQuery, (cte) -> {
|
||||
final JpaCriteriaQuery<Tuple> innerQuery = builder.createTupleQuery();
|
||||
final JpaRoot<Account> accountRoot = innerQuery.from( Account.class );
|
||||
final JpaRoot<Tuple> cteRoot = innerQuery.from( cte );
|
||||
innerQuery.multiselect(
|
||||
accountRoot.get( "id" ),
|
||||
accountRoot.get( "name" ),
|
||||
accountRoot.get( "parent" ).get( "id" )
|
||||
);
|
||||
innerQuery.where( builder.equal( accountRoot.get( "id" ), cteRoot.get( "parent_id" ) ) );
|
||||
return innerQuery;
|
||||
} );
|
||||
final JpaRoot<Tuple> root = query.from( accountChainTable );
|
||||
query.multiselect( root.get( "id" ), root.get( "name" ), root.get( "parent_id" ) );
|
||||
final SqmQueryImplementor<Tuple> querySqm = (SqmQueryImplementor<Tuple>) entityManager.createQuery( query );
|
||||
assertThat( querySqm.getSqmStatement() )
|
||||
.withFailMessage( "Query statement should have been copied: [%s]", querySqm.getSqmStatement() )
|
||||
.isNotSameAs( query );
|
||||
final List<Tuple> resultList = querySqm.getResultList();
|
||||
assertThat( resultList ).hasSize( 2 );
|
||||
assertThat( resultList.get( 0 ).get( 1 ) ).isEqualTo( "Child Account" );
|
||||
assertThat( resultList.get( 1 ).get( 1 ) ).isEqualTo( "Parent Account" );
|
||||
} );
|
||||
}
|
||||
|
||||
|
||||
@Entity( name = "Account" )
|
||||
public static class Account {
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private Long id;
|
||||
|
||||
private String name;
|
||||
|
||||
@OneToOne
|
||||
private Account parent;
|
||||
|
||||
public Account() {
|
||||
}
|
||||
|
||||
public Account(String name, Account parent) {
|
||||
this.name = name;
|
||||
this.parent = parent;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue