Fix Could not locate TableGroup exception when a join predicate contain an implicit join
This commit is contained in:
parent
bce2737c44
commit
f1d6dc890a
|
@ -1930,8 +1930,8 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
||||||
fromClauseIndex.register( sqmRoot, tableGroup );
|
fromClauseIndex.register( sqmRoot, tableGroup );
|
||||||
currentQuerySpec().getFromClause().addRoot( tableGroup );
|
currentQuerySpec().getFromClause().addRoot( tableGroup );
|
||||||
|
|
||||||
consumeExplicitJoins( sqmRoot, tableGroup );
|
|
||||||
consumeReusablePaths( sqmRoot, tableGroup );
|
consumeReusablePaths( sqmRoot, tableGroup );
|
||||||
|
consumeExplicitJoins( sqmRoot, tableGroup );
|
||||||
}
|
}
|
||||||
|
|
||||||
private EntityPersister resolveEntityPersister(EntityDomainType<?> entityDomainType) {
|
private EntityPersister resolveEntityPersister(EntityDomainType<?> entityDomainType) {
|
||||||
|
@ -2024,6 +2024,8 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
||||||
|
|
||||||
getFromClauseIndex().register( sqmJoin, joinedTableGroup, joinPath );
|
getFromClauseIndex().register( sqmJoin, joinedTableGroup, joinPath );
|
||||||
|
|
||||||
|
consumeReusablePaths( sqmJoin, joinedTableGroup );
|
||||||
|
|
||||||
// add any additional join restrictions
|
// add any additional join restrictions
|
||||||
if ( sqmJoin.getJoinPredicate() != null ) {
|
if ( sqmJoin.getJoinPredicate() != null ) {
|
||||||
if ( sqmJoin.isFetched() ) {
|
if ( sqmJoin.isFetched() ) {
|
||||||
|
@ -2040,7 +2042,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
||||||
}
|
}
|
||||||
|
|
||||||
consumeExplicitJoins( sqmJoin, joinedTableGroup );
|
consumeExplicitJoins( sqmJoin, joinedTableGroup );
|
||||||
consumeReusablePaths( sqmJoin, joinedTableGroup );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private NavigablePath getJoinNavigablePath(
|
private NavigablePath getJoinNavigablePath(
|
||||||
|
|
|
@ -0,0 +1,447 @@
|
||||||
|
package org.hibernate.test.join;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.ManyToOne;
|
||||||
|
import javax.persistence.MappedSuperclass;
|
||||||
|
import javax.persistence.OneToOne;
|
||||||
|
import javax.persistence.PrimaryKeyJoinColumn;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
import javax.persistence.Tuple;
|
||||||
|
|
||||||
|
import org.hibernate.testing.orm.junit.EntityManagerFactoryScope;
|
||||||
|
import org.hibernate.testing.orm.junit.Jpa;
|
||||||
|
import org.junit.jupiter.api.AfterAll;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Disabled;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||||
|
|
||||||
|
@Jpa(
|
||||||
|
annotatedClasses = {
|
||||||
|
OuterJoinTest.A.class,
|
||||||
|
OuterJoinTest.B.class,
|
||||||
|
OuterJoinTest.C.class,
|
||||||
|
OuterJoinTest.D.class,
|
||||||
|
OuterJoinTest.Association.class
|
||||||
|
}
|
||||||
|
)
|
||||||
|
public class OuterJoinTest {
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
public void setUp(EntityManagerFactoryScope scope) throws Exception {
|
||||||
|
scope.inTransaction( em -> {
|
||||||
|
Association association = new Association( 1l, "association" );
|
||||||
|
em.merge( association );
|
||||||
|
|
||||||
|
em.merge( new A( 1L, "a", association ) );
|
||||||
|
em.merge( new A( 2L, "b", association ) );
|
||||||
|
em.merge( new A( 3L, "c", association ) );
|
||||||
|
|
||||||
|
em.merge( new B( 1L, "d", association ) );
|
||||||
|
em.merge( new B( 2L, "e", association ) );
|
||||||
|
em.merge( new B( 3L, "f", association ) );
|
||||||
|
|
||||||
|
em.merge( new C( 1L, "g", association ) );
|
||||||
|
em.merge( new C( 2L, "h", association ) );
|
||||||
|
em.merge( new C( 4L, "j", association ) );
|
||||||
|
|
||||||
|
em.merge( new D( 1L, "k", association ) );
|
||||||
|
em.merge( new D( 2L, "l", association ) );
|
||||||
|
em.merge( new D( 4L, "m", association ) );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterAll
|
||||||
|
public void tearDown(EntityManagerFactoryScope scope) {
|
||||||
|
scope.inTransaction(
|
||||||
|
entityManager -> {
|
||||||
|
entityManager.createQuery( "delete from A" ).executeUpdate();
|
||||||
|
entityManager.createQuery( "delete from B" ).executeUpdate();
|
||||||
|
entityManager.createQuery( "delete from C" ).executeUpdate();
|
||||||
|
entityManager.createQuery( "delete from D" ).executeUpdate();
|
||||||
|
entityManager.createQuery( "delete from Association" ).executeUpdate();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void mergeIt(EntityManagerFactoryScope scope) {
|
||||||
|
scope.inTransaction( em -> {
|
||||||
|
Association association = new Association( 1l, "association" );
|
||||||
|
em.merge( association );
|
||||||
|
|
||||||
|
em.merge( new A( 1L, "a", association ) );
|
||||||
|
em.merge( new A( 2L, "b", association ) );
|
||||||
|
em.merge( new A( 3L, "c", association ) );
|
||||||
|
|
||||||
|
em.merge( new B( 1L, "d", association ) );
|
||||||
|
em.merge( new B( 2L, "e", association ) );
|
||||||
|
em.merge( new B( 3L, "f", association ) );
|
||||||
|
|
||||||
|
em.merge( new C( 1L, "g", association ) );
|
||||||
|
em.merge( new C( 2L, "h", association ) );
|
||||||
|
em.merge( new C( 4L, "j", association ) );
|
||||||
|
|
||||||
|
em.merge( new D( 1L, "k", association ) );
|
||||||
|
em.merge( new D( 2L, "l", association ) );
|
||||||
|
em.merge( new D( 4L, "m", association ) );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testJoinOrderWithRightJoin(EntityManagerFactoryScope scope) {
|
||||||
|
scope.inTransaction( em -> {
|
||||||
|
List<Tuple> resultList = em.createQuery(
|
||||||
|
"SELECT COALESCE(a.key, b.key, c.key, d.key), a.value, b.value, c.value, d.value " +
|
||||||
|
"FROM A a " +
|
||||||
|
"INNER JOIN B b ON a.key = b.key " +
|
||||||
|
"RIGHT JOIN C c ON a.key = c.key " +
|
||||||
|
"INNER JOIN D d ON d.key = c.key " +
|
||||||
|
"ORDER BY COALESCE(a.key, b.key, c.key, d.key) ASC",
|
||||||
|
Tuple.class
|
||||||
|
)
|
||||||
|
.getResultList();
|
||||||
|
|
||||||
|
assertEquals( 3, resultList.size() );
|
||||||
|
|
||||||
|
assertEquals( "a", resultList.get( 0 ).get( 1 ) );
|
||||||
|
assertEquals( "d", resultList.get( 0 ).get( 2 ) );
|
||||||
|
assertEquals( "g", resultList.get( 0 ).get( 3 ) );
|
||||||
|
assertEquals( "k", resultList.get( 0 ).get( 4 ) );
|
||||||
|
|
||||||
|
assertEquals( "b", resultList.get( 1 ).get( 1 ) );
|
||||||
|
assertEquals( "e", resultList.get( 1 ).get( 2 ) );
|
||||||
|
assertEquals( "h", resultList.get( 1 ).get( 3 ) );
|
||||||
|
assertEquals( "l", resultList.get( 1 ).get( 4 ) );
|
||||||
|
|
||||||
|
assertNull( resultList.get( 2 ).get( 1 ) );
|
||||||
|
assertNull( resultList.get( 2 ).get( 2 ) );
|
||||||
|
assertEquals( "j", resultList.get( 2 ).get( 3 ) );
|
||||||
|
assertEquals( "m", resultList.get( 2 ).get( 4 ) );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testJoinOrderWithRightNormalJoin(EntityManagerFactoryScope scope) {
|
||||||
|
scope.inTransaction( em -> {
|
||||||
|
List<Tuple> resultList = em.createQuery(
|
||||||
|
"SELECT COALESCE(a.key, b.key, c.key, d.key), a.value, b.value, c.value, d.value " +
|
||||||
|
"FROM A a " +
|
||||||
|
"INNER JOIN B b ON a.key = b.key " +
|
||||||
|
"RIGHT JOIN a.cAssociationByKey c " +
|
||||||
|
"INNER JOIN D d ON d.key = c.key " +
|
||||||
|
"ORDER BY COALESCE(a.key, b.key, c.key, d.key) ASC",
|
||||||
|
Tuple.class
|
||||||
|
)
|
||||||
|
.getResultList();
|
||||||
|
|
||||||
|
assertEquals( 3, resultList.size() );
|
||||||
|
|
||||||
|
assertEquals( "a", resultList.get( 0 ).get( 1 ) );
|
||||||
|
assertEquals( "d", resultList.get( 0 ).get( 2 ) );
|
||||||
|
assertEquals( "g", resultList.get( 0 ).get( 3 ) );
|
||||||
|
assertEquals( "k", resultList.get( 0 ).get( 4 ) );
|
||||||
|
|
||||||
|
assertEquals( "b", resultList.get( 1 ).get( 1 ) );
|
||||||
|
assertEquals( "e", resultList.get( 1 ).get( 2 ) );
|
||||||
|
assertEquals( "h", resultList.get( 1 ).get( 3 ) );
|
||||||
|
assertEquals( "l", resultList.get( 1 ).get( 4 ) );
|
||||||
|
|
||||||
|
assertNull( resultList.get( 2 ).get( 1 ) );
|
||||||
|
assertNull( resultList.get( 2 ).get( 2 ) );
|
||||||
|
assertEquals( "j", resultList.get( 2 ).get( 3 ) );
|
||||||
|
assertEquals( "m", resultList.get( 2 ).get( 4 ) );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testJoinOrderWithRightJoinWithIdDereference(EntityManagerFactoryScope scope) {
|
||||||
|
scope.inTransaction( em -> {
|
||||||
|
List<Tuple> resultList = em.createQuery(
|
||||||
|
"SELECT COALESCE(a.key, b.key, c.key, d.key), a.value, b.value, c.value, d.value " +
|
||||||
|
"FROM A a " +
|
||||||
|
"INNER JOIN B b ON a.key = b.key AND a.association.key = b.association.key " +
|
||||||
|
"RIGHT JOIN C c ON a.key = c.key AND a.association.key = c.association.key " +
|
||||||
|
"INNER JOIN D d ON d.key = c.key AND d.association.key = c.association.key " +
|
||||||
|
"ORDER BY COALESCE(a.key, b.key, c.key, d.key) ASC",
|
||||||
|
Tuple.class
|
||||||
|
).getResultList();
|
||||||
|
|
||||||
|
assertEquals( 3, resultList.size() );
|
||||||
|
|
||||||
|
assertEquals( "a", resultList.get( 0 ).get( 1 ) );
|
||||||
|
assertEquals( "d", resultList.get( 0 ).get( 2 ) );
|
||||||
|
assertEquals( "g", resultList.get( 0 ).get( 3 ) );
|
||||||
|
assertEquals( "k", resultList.get( 0 ).get( 4 ) );
|
||||||
|
|
||||||
|
assertEquals( "b", resultList.get( 1 ).get( 1 ) );
|
||||||
|
assertEquals( "e", resultList.get( 1 ).get( 2 ) );
|
||||||
|
assertEquals( "h", resultList.get( 1 ).get( 3 ) );
|
||||||
|
assertEquals( "l", resultList.get( 1 ).get( 4 ) );
|
||||||
|
|
||||||
|
assertNull( resultList.get( 2 ).get( 1 ) );
|
||||||
|
assertNull( resultList.get( 2 ).get( 2 ) );
|
||||||
|
assertEquals( "j", resultList.get( 2 ).get( 3 ) );
|
||||||
|
assertEquals( "m", resultList.get( 2 ).get( 4 ) );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testJoinOrderWithRightNormalJoinWithIdDereference(EntityManagerFactoryScope scope) {
|
||||||
|
scope.inTransaction( em -> {
|
||||||
|
List<Tuple> resultList = em.createQuery(
|
||||||
|
"SELECT COALESCE(a.key, b.key, c.key, d.key), a.value, b.value, c.value, d.value " +
|
||||||
|
"FROM A a " +
|
||||||
|
"INNER JOIN B b ON a.key = b.key AND a.association.key = b.association.key " +
|
||||||
|
"RIGHT JOIN a.cAssociationByKey c ON a.key = c.key AND a.association.key = c.association.key " +
|
||||||
|
"INNER JOIN D d ON d.key = c.key AND d.association.key = c.association.key " +
|
||||||
|
"ORDER BY COALESCE(a.key, b.key, c.key, d.key) ASC",
|
||||||
|
Tuple.class
|
||||||
|
).getResultList();
|
||||||
|
|
||||||
|
assertEquals( 3, resultList.size() );
|
||||||
|
|
||||||
|
assertEquals( "a", resultList.get( 0 ).get( 1 ) );
|
||||||
|
assertEquals( "d", resultList.get( 0 ).get( 2 ) );
|
||||||
|
assertEquals( "g", resultList.get( 0 ).get( 3 ) );
|
||||||
|
assertEquals( "k", resultList.get( 0 ).get( 4 ) );
|
||||||
|
|
||||||
|
assertEquals( "b", resultList.get( 1 ).get( 1 ) );
|
||||||
|
assertEquals( "e", resultList.get( 1 ).get( 2 ) );
|
||||||
|
assertEquals( "h", resultList.get( 1 ).get( 3 ) );
|
||||||
|
assertEquals( "l", resultList.get( 1 ).get( 4 ) );
|
||||||
|
|
||||||
|
assertNull( resultList.get( 2 ).get( 1 ) );
|
||||||
|
assertNull( resultList.get( 2 ).get( 2 ) );
|
||||||
|
assertEquals( "j", resultList.get( 2 ).get( 3 ) );
|
||||||
|
assertEquals( "m", resultList.get( 2 ).get( 4 ) );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testJoinOrderWithRightJoinWithInnerImplicitJoins(EntityManagerFactoryScope scope) {
|
||||||
|
scope.inTransaction( em -> {
|
||||||
|
List<Tuple> resultList = em.createQuery(
|
||||||
|
"SELECT COALESCE(a.key,b.key,c.key,d.key) AS key, a.value AS aValue, b.value AS bValue, c.value AS cValue, d.value AS dValue " +
|
||||||
|
"FROM A a JOIN a.association association_1 JOIN B b ON (EXISTS (SELECT 1 FROM b.association _synth_subquery_0 WHERE a.key = b.key AND association_1.value = _synth_subquery_0.value))" +
|
||||||
|
"RIGHT JOIN C c ON (EXISTS (SELECT 1 FROM c.association _synth_subquery_0 WHERE a.key = c.key AND association_1.value = _synth_subquery_0.value)) " +
|
||||||
|
"JOIN c.association association_5 " +
|
||||||
|
"JOIN D d ON (EXISTS (SELECT 1 FROM d.association _synth_subquery_0 WHERE d.key = c.key AND _synth_subquery_0.value = association_5.value))" +
|
||||||
|
" ORDER BY COALESCE(a.key,b.key,c.key,d.key) ASC",
|
||||||
|
Tuple.class
|
||||||
|
).getResultList();
|
||||||
|
|
||||||
|
assertEquals( 3, resultList.size() );
|
||||||
|
|
||||||
|
assertEquals( "a", resultList.get( 0 ).get( 1 ) );
|
||||||
|
assertEquals( "d", resultList.get( 0 ).get( 2 ) );
|
||||||
|
assertEquals( "g", resultList.get( 0 ).get( 3 ) );
|
||||||
|
assertEquals( "k", resultList.get( 0 ).get( 4 ) );
|
||||||
|
|
||||||
|
assertEquals( "b", resultList.get( 1 ).get( 1 ) );
|
||||||
|
assertEquals( "e", resultList.get( 1 ).get( 2 ) );
|
||||||
|
assertEquals( "h", resultList.get( 1 ).get( 3 ) );
|
||||||
|
assertEquals( "l", resultList.get( 1 ).get( 4 ) );
|
||||||
|
|
||||||
|
assertNull( resultList.get( 2 ).get( 1 ) );
|
||||||
|
assertNull( resultList.get( 2 ).get( 2 ) );
|
||||||
|
assertEquals( "j", resultList.get( 2 ).get( 3 ) );
|
||||||
|
assertEquals( "m", resultList.get( 2 ).get( 4 ) );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Disabled("Hibernate doesn't support implicit joins")
|
||||||
|
public void testJoinOrderWithRightNormalJoinWithInnerImplicitJoins(EntityManagerFactoryScope scope) {
|
||||||
|
scope.inTransaction( em -> {
|
||||||
|
List<Tuple> resultList = em.createQuery(
|
||||||
|
"SELECT COALESCE(a.key, b.key, c.key, d.key), a.value, b.value, c.value, d.value " +
|
||||||
|
"FROM A a " +
|
||||||
|
"INNER JOIN B b ON a.key = b.key AND a.association.value = b.association.value " +
|
||||||
|
"RIGHT JOIN a.cAssociationByKey c ON a.key = c.key AND a.association.value = c.association.value " +
|
||||||
|
"INNER JOIN D d ON d.key = c.key AND d.association.value = c.association.value " +
|
||||||
|
"ORDER BY COALESCE(a.key, b.key, c.key, d.key) ASC",
|
||||||
|
Tuple.class
|
||||||
|
).getResultList();
|
||||||
|
|
||||||
|
assertEquals( 3, resultList.size() );
|
||||||
|
|
||||||
|
assertEquals( "a", resultList.get( 0 ).get( 1 ) );
|
||||||
|
assertEquals( "d", resultList.get( 0 ).get( 2 ) );
|
||||||
|
assertEquals( "g", resultList.get( 0 ).get( 3 ) );
|
||||||
|
assertEquals( "k", resultList.get( 0 ).get( 4 ) );
|
||||||
|
|
||||||
|
assertEquals( "b", resultList.get( 1 ).get( 1 ) );
|
||||||
|
assertEquals( "e", resultList.get( 1 ).get( 2 ) );
|
||||||
|
assertEquals( "h", resultList.get( 1 ).get( 3 ) );
|
||||||
|
assertEquals( "l", resultList.get( 1 ).get( 4 ) );
|
||||||
|
|
||||||
|
assertNull( resultList.get( 2 ).get( 1 ) );
|
||||||
|
assertNull( resultList.get( 2 ).get( 2 ) );
|
||||||
|
assertEquals( "j", resultList.get( 2 ).get( 3 ) );
|
||||||
|
assertEquals( "m", resultList.get( 2 ).get( 4 ) );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testJoinOrderWithRightJoinWithNonOptionalAssociationProjections(EntityManagerFactoryScope scope) {
|
||||||
|
scope.inTransaction( em -> {
|
||||||
|
List<Tuple> resultList = em.createQuery(
|
||||||
|
"SELECT COALESCE(a.key, b.key, c.key, d.key), a.value, b.value, c.value, d.value " +
|
||||||
|
"FROM A a " +
|
||||||
|
"INNER JOIN B b ON a.key = b.key " +
|
||||||
|
"RIGHT JOIN C c ON a.key = c.key " +
|
||||||
|
"INNER JOIN D d ON d.key = c.key " +
|
||||||
|
"ORDER BY COALESCE(a.key, b.key, c.key, d.key) ASC",
|
||||||
|
Tuple.class
|
||||||
|
).getResultList();
|
||||||
|
|
||||||
|
assertEquals( 3, resultList.size() );
|
||||||
|
|
||||||
|
assertEquals( "a", resultList.get( 0 ).get( 1 ) );
|
||||||
|
assertEquals( "d", resultList.get( 0 ).get( 2 ) );
|
||||||
|
assertEquals( "g", resultList.get( 0 ).get( 3 ) );
|
||||||
|
assertEquals( "k", resultList.get( 0 ).get( 4 ) );
|
||||||
|
|
||||||
|
assertEquals( "b", resultList.get( 1 ).get( 1 ) );
|
||||||
|
assertEquals( "e", resultList.get( 1 ).get( 2 ) );
|
||||||
|
assertEquals( "h", resultList.get( 1 ).get( 3 ) );
|
||||||
|
assertEquals( "l", resultList.get( 1 ).get( 4 ) );
|
||||||
|
|
||||||
|
assertNull( resultList.get( 2 ).get( 1 ) );
|
||||||
|
assertNull( resultList.get( 2 ).get( 2 ) );
|
||||||
|
assertEquals( "j", resultList.get( 2 ).get( 3 ) );
|
||||||
|
assertEquals( "m", resultList.get( 2 ).get( 4 ) );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testJoinOrderWithRightNormalJoinWithNonOptionalAssociationProjections(EntityManagerFactoryScope scope) {
|
||||||
|
scope.inTransaction( em -> {
|
||||||
|
List<Tuple> resultList = em.createQuery(
|
||||||
|
"SELECT COALESCE(a.key, b.key, c.key, d.key), a.value, b.value, c.value, d.value " +
|
||||||
|
"FROM A a " +
|
||||||
|
"INNER JOIN B b ON a.key = b.key " +
|
||||||
|
"RIGHT JOIN a.cAssociationByKey c ON a.key = c.key " +
|
||||||
|
"INNER JOIN D d ON d.key = c.key " +
|
||||||
|
"ORDER BY COALESCE(a.key, b.key, c.key, d.key) ASC",
|
||||||
|
Tuple.class
|
||||||
|
).getResultList();
|
||||||
|
|
||||||
|
assertEquals( 3, resultList.size() );
|
||||||
|
|
||||||
|
assertEquals( "a", resultList.get( 0 ).get( 1 ) );
|
||||||
|
assertEquals( "d", resultList.get( 0 ).get( 2 ) );
|
||||||
|
assertEquals( "g", resultList.get( 0 ).get( 3 ) );
|
||||||
|
assertEquals( "k", resultList.get( 0 ).get( 4 ) );
|
||||||
|
|
||||||
|
assertEquals( "b", resultList.get( 1 ).get( 1 ) );
|
||||||
|
assertEquals( "e", resultList.get( 1 ).get( 2 ) );
|
||||||
|
assertEquals( "h", resultList.get( 1 ).get( 3 ) );
|
||||||
|
assertEquals( "l", resultList.get( 1 ).get( 4 ) );
|
||||||
|
|
||||||
|
assertNull( resultList.get( 2 ).get( 1 ) );
|
||||||
|
assertNull( resultList.get( 2 ).get( 2 ) );
|
||||||
|
assertEquals( "j", resultList.get( 2 ).get( 3 ) );
|
||||||
|
assertEquals( "m", resultList.get( 2 ).get( 4 ) );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
@MappedSuperclass
|
||||||
|
public static class BaseEntity {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@Column(name = "key_id")
|
||||||
|
Long key;
|
||||||
|
|
||||||
|
String value;
|
||||||
|
|
||||||
|
@ManyToOne(optional = false)
|
||||||
|
Association association;
|
||||||
|
|
||||||
|
public BaseEntity() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public BaseEntity(Long key, String value, Association association) {
|
||||||
|
this.key = key;
|
||||||
|
this.value = value;
|
||||||
|
this.association = association;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity(name = "A")
|
||||||
|
@Table(name = "a")
|
||||||
|
public static class A extends BaseEntity {
|
||||||
|
|
||||||
|
@OneToOne
|
||||||
|
@PrimaryKeyJoinColumn(columnDefinition = "association_key", referencedColumnName = "key_id")
|
||||||
|
private C cAssociationByKey;
|
||||||
|
|
||||||
|
public A() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public A(Long key, String value, Association association) {
|
||||||
|
super( key, value, association );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Entity(name = "B")
|
||||||
|
@Table(name = "b")
|
||||||
|
public static class B extends BaseEntity {
|
||||||
|
public B() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public B(Long key, String value, Association association) {
|
||||||
|
super( key, value, association );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity(name = "C")
|
||||||
|
@Table(name = "c")
|
||||||
|
public static class C extends BaseEntity {
|
||||||
|
public C() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public C(Long key, String value, Association association) {
|
||||||
|
super( key, value, association );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity(name = "D")
|
||||||
|
@Table(name = "d")
|
||||||
|
public static class D extends BaseEntity {
|
||||||
|
public D() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public D(Long key, String value, Association association) {
|
||||||
|
super( key, value, association );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity(name = "Association")
|
||||||
|
@Table(name = "association")
|
||||||
|
public static class Association {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@Column(name = "key_id")
|
||||||
|
private Long key;
|
||||||
|
|
||||||
|
private String value;
|
||||||
|
|
||||||
|
public Association() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Association(Long key, String value) {
|
||||||
|
this.key = key;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -258,7 +258,7 @@ public class ManyToManySizeTest2 {
|
||||||
Student.class
|
Student.class
|
||||||
).getResultList();
|
).getResultList();
|
||||||
assertEquals( 0, students.size() );
|
assertEquals( 0, students.size() );
|
||||||
statementInspector.assertNumberOfJoins( 0, 4 );
|
statementInspector.assertNumberOfJoins( 0, 3 );
|
||||||
|
|
||||||
students = session.createQuery(
|
students = session.createQuery(
|
||||||
"select distinct student from Student student left join fetch student.teacher t left join fetch t.skills where size(student.teacher.skills) > 1",
|
"select distinct student from Student student left join fetch student.teacher t left join fetch t.skills where size(student.teacher.skills) > 1",
|
||||||
|
|
|
@ -259,7 +259,7 @@ public class OneToManySizeTest2 {
|
||||||
"where size(student.teacher.students) > 2",
|
"where size(student.teacher.students) > 2",
|
||||||
Student.class
|
Student.class
|
||||||
).getResultList();
|
).getResultList();
|
||||||
assertEquals( 3, countNumberOfJoins( statementInspector.getSqlQueries().get( 0 ) ) );
|
assertEquals( 2, countNumberOfJoins( statementInspector.getSqlQueries().get( 0 ) ) );
|
||||||
assertEquals( 0, students.size() );
|
assertEquals( 0, students.size() );
|
||||||
|
|
||||||
students = session.createQuery(
|
students = session.createQuery(
|
||||||
|
@ -436,7 +436,7 @@ public class OneToManySizeTest2 {
|
||||||
Student.class
|
Student.class
|
||||||
).getResultList();
|
).getResultList();
|
||||||
// Since the join for "student.teacher" is never used and is a non-optional association we don't generate a SQL join for it
|
// Since the join for "student.teacher" is never used and is a non-optional association we don't generate a SQL join for it
|
||||||
assertEquals( 3, countNumberOfJoins( statementInspector.getSqlQueries().get( 0 ) ) );
|
assertEquals( 2, countNumberOfJoins( statementInspector.getSqlQueries().get( 0 ) ) );
|
||||||
assertEquals( 3L, students.size() );
|
assertEquals( 3L, students.size() );
|
||||||
assertTrue( Hibernate.isInitialized( students.get( 0 ).getTeacher().getStudents() ) );
|
assertTrue( Hibernate.isInitialized( students.get( 0 ).getTeacher().getStudents() ) );
|
||||||
assertTrue( Hibernate.isInitialized( students.get( 1 ).getTeacher().getStudents() ) );
|
assertTrue( Hibernate.isInitialized( students.get( 1 ).getTeacher().getStudents() ) );
|
||||||
|
@ -452,7 +452,7 @@ public class OneToManySizeTest2 {
|
||||||
Student.class
|
Student.class
|
||||||
).getResultList();
|
).getResultList();
|
||||||
// Since the join for "student.teacher" is never used and is a non-optional association we don't generate a SQL join for it
|
// Since the join for "student.teacher" is never used and is a non-optional association we don't generate a SQL join for it
|
||||||
assertEquals( 3, countNumberOfJoins( statementInspector.getSqlQueries().get( 0 ) ) );
|
assertEquals( 2, countNumberOfJoins( statementInspector.getSqlQueries().get( 0 ) ) );
|
||||||
assertEquals( 3L, students.size() );
|
assertEquals( 3L, students.size() );
|
||||||
assertTrue( Hibernate.isInitialized( students.get( 0 ).getTeacher().getStudents() ) );
|
assertTrue( Hibernate.isInitialized( students.get( 0 ).getTeacher().getStudents() ) );
|
||||||
assertTrue( Hibernate.isInitialized( students.get( 1 ).getTeacher().getStudents() ) );
|
assertTrue( Hibernate.isInitialized( students.get( 1 ).getTeacher().getStudents() ) );
|
||||||
|
@ -468,7 +468,7 @@ public class OneToManySizeTest2 {
|
||||||
Student.class
|
Student.class
|
||||||
).getResultList();
|
).getResultList();
|
||||||
// Since the join for "student.teacher" is never used and is a non-optional association we don't generate a SQL join for it
|
// Since the join for "student.teacher" is never used and is a non-optional association we don't generate a SQL join for it
|
||||||
assertEquals( 3, countNumberOfJoins( statementInspector.getSqlQueries().get( 0 ) ) );
|
assertEquals( 2, countNumberOfJoins( statementInspector.getSqlQueries().get( 0 ) ) );
|
||||||
assertEquals( 2L, students.size() );
|
assertEquals( 2L, students.size() );
|
||||||
assertTrue( Hibernate.isInitialized( students.get( 0 ).getTeacher().getStudents() ) );
|
assertTrue( Hibernate.isInitialized( students.get( 0 ).getTeacher().getStudents() ) );
|
||||||
assertTrue( Hibernate.isInitialized( students.get( 1 ).getTeacher().getStudents() ) );
|
assertTrue( Hibernate.isInitialized( students.get( 1 ).getTeacher().getStudents() ) );
|
||||||
|
|
|
@ -1,399 +0,0 @@
|
||||||
package org.hibernate.test.join;
|
|
||||||
|
|
||||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Ignore;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import javax.persistence.*;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
import static org.junit.Assert.assertNull;
|
|
||||||
|
|
||||||
public class OuterJoinTest extends BaseCoreFunctionalTestCase {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Class<?>[] getAnnotatedClasses() {
|
|
||||||
return new Class<?>[]{ A.class, B.class, C.class, D.class, Association.class };
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@MappedSuperclass
|
|
||||||
public static class BaseEntity {
|
|
||||||
|
|
||||||
@Id
|
|
||||||
@Column(name = "key_id")
|
|
||||||
Long key;
|
|
||||||
|
|
||||||
String value;
|
|
||||||
|
|
||||||
@ManyToOne(optional = false)
|
|
||||||
Association association;
|
|
||||||
|
|
||||||
public BaseEntity() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public BaseEntity(Long key, String value, Association association) {
|
|
||||||
this.key = key;
|
|
||||||
this.value = value;
|
|
||||||
this.association = association;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Entity(name = "A")
|
|
||||||
@Table(name = "a")
|
|
||||||
public static class A extends BaseEntity {
|
|
||||||
|
|
||||||
@OneToOne
|
|
||||||
@PrimaryKeyJoinColumn(columnDefinition = "association_key", referencedColumnName = "key_id")
|
|
||||||
private C cAssociationByKey;
|
|
||||||
|
|
||||||
public A() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public A(Long key, String value, Association association) {
|
|
||||||
super(key, value, association);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Entity(name = "B")
|
|
||||||
@Table(name = "b")
|
|
||||||
public static class B extends BaseEntity {
|
|
||||||
public B() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public B(Long key, String value, Association association) {
|
|
||||||
super(key, value, association);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Entity(name = "C")
|
|
||||||
@Table(name = "c")
|
|
||||||
public static class C extends BaseEntity {
|
|
||||||
public C() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public C(Long key, String value, Association association) {
|
|
||||||
super(key, value, association);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Entity(name = "D")
|
|
||||||
@Table(name = "d")
|
|
||||||
public static class D extends BaseEntity {
|
|
||||||
public D() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public D(Long key, String value, Association association) {
|
|
||||||
super(key, value, association);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Entity(name = "Association")
|
|
||||||
@Table(name = "association")
|
|
||||||
public static class Association {
|
|
||||||
|
|
||||||
@Id
|
|
||||||
@Column(name = "key_id")
|
|
||||||
private Long key;
|
|
||||||
|
|
||||||
private String value;
|
|
||||||
|
|
||||||
public Association() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public Association(Long key, String value) {
|
|
||||||
this.key = key;
|
|
||||||
this.value = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Before
|
|
||||||
public void setUp() throws Exception {
|
|
||||||
doInJPA( this::sessionFactory, em -> {
|
|
||||||
Association association = new Association(1l, "association");
|
|
||||||
em.merge(association);
|
|
||||||
|
|
||||||
em.merge(new A(1L, "a", association));
|
|
||||||
em.merge(new A(2L, "b", association));
|
|
||||||
em.merge(new A(3L, "c", association));
|
|
||||||
|
|
||||||
em.merge(new B(1L, "d", association));
|
|
||||||
em.merge(new B(2L, "e", association));
|
|
||||||
em.merge(new B(3L, "f", association));
|
|
||||||
|
|
||||||
em.merge(new C(1L, "g", association));
|
|
||||||
em.merge(new C(2L, "h", association));
|
|
||||||
em.merge(new C(4L, "j", association));
|
|
||||||
|
|
||||||
em.merge(new D(1L, "k", association));
|
|
||||||
em.merge(new D(2L, "l", association));
|
|
||||||
em.merge(new D(4L, "m", association));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void mergeIt(){
|
|
||||||
doInJPA( this::sessionFactory, em -> {
|
|
||||||
Association association = new Association(1l, "association");
|
|
||||||
em.merge(association);
|
|
||||||
|
|
||||||
em.merge(new A(1L, "a", association));
|
|
||||||
em.merge(new A(2L, "b", association));
|
|
||||||
em.merge(new A(3L, "c", association));
|
|
||||||
|
|
||||||
em.merge(new B(1L, "d", association));
|
|
||||||
em.merge(new B(2L, "e", association));
|
|
||||||
em.merge(new B(3L, "f", association));
|
|
||||||
|
|
||||||
em.merge(new C(1L, "g", association));
|
|
||||||
em.merge(new C(2L, "h", association));
|
|
||||||
em.merge(new C(4L, "j", association));
|
|
||||||
|
|
||||||
em.merge(new D(1L, "k", association));
|
|
||||||
em.merge(new D(2L, "l", association));
|
|
||||||
em.merge(new D(4L, "m", association));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testJoinOrderWithRightJoin() {
|
|
||||||
doInJPA( this::sessionFactory, em -> {
|
|
||||||
List<Tuple> resultList = em.createQuery("SELECT COALESCE(a.key, b.key, c.key, d.key), a.value, b.value, c.value, d.value " +
|
|
||||||
"FROM A a " +
|
|
||||||
"INNER JOIN B b ON a.key = b.key " +
|
|
||||||
"RIGHT JOIN C c ON a.key = c.key " +
|
|
||||||
"INNER JOIN D d ON d.key = c.key " +
|
|
||||||
"ORDER BY COALESCE(a.key, b.key, c.key, d.key) ASC", Tuple.class)
|
|
||||||
.getResultList();
|
|
||||||
|
|
||||||
assertEquals(3, resultList.size());
|
|
||||||
|
|
||||||
assertEquals("a", resultList.get(0).get(1));
|
|
||||||
assertEquals("d", resultList.get(0).get(2));
|
|
||||||
assertEquals("g", resultList.get(0).get(3));
|
|
||||||
assertEquals("k", resultList.get(0).get(4));
|
|
||||||
|
|
||||||
assertEquals("b", resultList.get(1).get(1));
|
|
||||||
assertEquals("e", resultList.get(1).get(2));
|
|
||||||
assertEquals("h", resultList.get(1).get(3));
|
|
||||||
assertEquals("l", resultList.get(1).get(4));
|
|
||||||
|
|
||||||
assertNull(resultList.get(2).get(1));
|
|
||||||
assertNull(resultList.get(2).get(2));
|
|
||||||
assertEquals("j", resultList.get(2).get(3));
|
|
||||||
assertEquals("m", resultList.get(2).get(4));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testJoinOrderWithRightNormalJoin() {
|
|
||||||
doInJPA( this::sessionFactory, em -> {
|
|
||||||
List<Tuple> resultList = em.createQuery("SELECT COALESCE(a.key, b.key, c.key, d.key), a.value, b.value, c.value, d.value " +
|
|
||||||
"FROM A a " +
|
|
||||||
"INNER JOIN B b ON a.key = b.key " +
|
|
||||||
"RIGHT JOIN a.cAssociationByKey c " +
|
|
||||||
"INNER JOIN D d ON d.key = c.key " +
|
|
||||||
"ORDER BY COALESCE(a.key, b.key, c.key, d.key) ASC", Tuple.class)
|
|
||||||
.getResultList();
|
|
||||||
|
|
||||||
assertEquals(3, resultList.size());
|
|
||||||
|
|
||||||
assertEquals("a", resultList.get(0).get(1));
|
|
||||||
assertEquals("d", resultList.get(0).get(2));
|
|
||||||
assertEquals("g", resultList.get(0).get(3));
|
|
||||||
assertEquals("k", resultList.get(0).get(4));
|
|
||||||
|
|
||||||
assertEquals("b", resultList.get(1).get(1));
|
|
||||||
assertEquals("e", resultList.get(1).get(2));
|
|
||||||
assertEquals("h", resultList.get(1).get(3));
|
|
||||||
assertEquals("l", resultList.get(1).get(4));
|
|
||||||
|
|
||||||
assertNull(resultList.get(2).get(1));
|
|
||||||
assertNull(resultList.get(2).get(2));
|
|
||||||
assertEquals("j", resultList.get(2).get(3));
|
|
||||||
assertEquals("m", resultList.get(2).get(4));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testJoinOrderWithRightJoinWithIdDereference() {
|
|
||||||
doInJPA( this::sessionFactory, em -> {
|
|
||||||
List<Tuple> resultList = em.createQuery("SELECT COALESCE(a.key, b.key, c.key, d.key), a.value, b.value, c.value, d.value " +
|
|
||||||
"FROM A a " +
|
|
||||||
"INNER JOIN B b ON a.key = b.key AND a.association.key = b.association.key " +
|
|
||||||
"RIGHT JOIN C c ON a.key = c.key AND a.association.key = c.association.key " +
|
|
||||||
"INNER JOIN D d ON d.key = c.key AND d.association.key = c.association.key " +
|
|
||||||
"ORDER BY COALESCE(a.key, b.key, c.key, d.key) ASC", Tuple.class).getResultList();
|
|
||||||
|
|
||||||
assertEquals(3, resultList.size());
|
|
||||||
|
|
||||||
assertEquals("a", resultList.get(0).get(1));
|
|
||||||
assertEquals("d", resultList.get(0).get(2));
|
|
||||||
assertEquals("g", resultList.get(0).get(3));
|
|
||||||
assertEquals("k", resultList.get(0).get(4));
|
|
||||||
|
|
||||||
assertEquals("b", resultList.get(1).get(1));
|
|
||||||
assertEquals("e", resultList.get(1).get(2));
|
|
||||||
assertEquals("h", resultList.get(1).get(3));
|
|
||||||
assertEquals("l", resultList.get(1).get(4));
|
|
||||||
|
|
||||||
assertNull(resultList.get(2).get(1));
|
|
||||||
assertNull(resultList.get(2).get(2));
|
|
||||||
assertEquals("j", resultList.get(2).get(3));
|
|
||||||
assertEquals("m", resultList.get(2).get(4));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testJoinOrderWithRightNormalJoinWithIdDereference() {
|
|
||||||
doInJPA( this::sessionFactory, em -> {
|
|
||||||
List<Tuple> resultList = em.createQuery("SELECT COALESCE(a.key, b.key, c.key, d.key), a.value, b.value, c.value, d.value " +
|
|
||||||
"FROM A a " +
|
|
||||||
"INNER JOIN B b ON a.key = b.key AND a.association.key = b.association.key " +
|
|
||||||
"RIGHT JOIN a.cAssociationByKey c ON a.key = c.key AND a.association.key = c.association.key " +
|
|
||||||
"INNER JOIN D d ON d.key = c.key AND d.association.key = c.association.key " +
|
|
||||||
"ORDER BY COALESCE(a.key, b.key, c.key, d.key) ASC", Tuple.class).getResultList();
|
|
||||||
|
|
||||||
assertEquals(3, resultList.size());
|
|
||||||
|
|
||||||
assertEquals("a", resultList.get(0).get(1));
|
|
||||||
assertEquals("d", resultList.get(0).get(2));
|
|
||||||
assertEquals("g", resultList.get(0).get(3));
|
|
||||||
assertEquals("k", resultList.get(0).get(4));
|
|
||||||
|
|
||||||
assertEquals("b", resultList.get(1).get(1));
|
|
||||||
assertEquals("e", resultList.get(1).get(2));
|
|
||||||
assertEquals("h", resultList.get(1).get(3));
|
|
||||||
assertEquals("l", resultList.get(1).get(4));
|
|
||||||
|
|
||||||
assertNull(resultList.get(2).get(1));
|
|
||||||
assertNull(resultList.get(2).get(2));
|
|
||||||
assertEquals("j", resultList.get(2).get(3));
|
|
||||||
assertEquals("m", resultList.get(2).get(4));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testJoinOrderWithRightJoinWithInnerImplicitJoins() {
|
|
||||||
doInJPA( this::sessionFactory, em -> {
|
|
||||||
List<Tuple> resultList = em.createQuery("SELECT COALESCE(a.key,b.key,c.key,d.key) AS key, a.value AS aValue, b.value AS bValue, c.value AS cValue, d.value AS dValue " +
|
|
||||||
"FROM A a JOIN a.association association_1 JOIN B b ON (EXISTS (SELECT 1 FROM b.association _synth_subquery_0 WHERE a.key = b.key AND association_1.value = _synth_subquery_0.value))" +
|
|
||||||
"RIGHT JOIN C c ON (EXISTS (SELECT 1 FROM c.association _synth_subquery_0 WHERE a.key = c.key AND association_1.value = _synth_subquery_0.value)) " +
|
|
||||||
"JOIN c.association association_5 " +
|
|
||||||
"JOIN D d ON (EXISTS (SELECT 1 FROM d.association _synth_subquery_0 WHERE d.key = c.key AND _synth_subquery_0.value = association_5.value))" +
|
|
||||||
" ORDER BY COALESCE(a.key,b.key,c.key,d.key) ASC", Tuple.class).getResultList();
|
|
||||||
|
|
||||||
assertEquals(3, resultList.size());
|
|
||||||
|
|
||||||
assertEquals("a", resultList.get(0).get(1));
|
|
||||||
assertEquals("d", resultList.get(0).get(2));
|
|
||||||
assertEquals("g", resultList.get(0).get(3));
|
|
||||||
assertEquals("k", resultList.get(0).get(4));
|
|
||||||
|
|
||||||
assertEquals("b", resultList.get(1).get(1));
|
|
||||||
assertEquals("e", resultList.get(1).get(2));
|
|
||||||
assertEquals("h", resultList.get(1).get(3));
|
|
||||||
assertEquals("l", resultList.get(1).get(4));
|
|
||||||
|
|
||||||
assertNull(resultList.get(2).get(1));
|
|
||||||
assertNull(resultList.get(2).get(2));
|
|
||||||
assertEquals("j", resultList.get(2).get(3));
|
|
||||||
assertEquals("m", resultList.get(2).get(4));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@Ignore("Hibernate doesn't support implicit joins")
|
|
||||||
public void testJoinOrderWithRightNormalJoinWithInnerImplicitJoins() {
|
|
||||||
doInJPA( this::sessionFactory, em -> {
|
|
||||||
List<Tuple> resultList = em.createQuery("SELECT COALESCE(a.key, b.key, c.key, d.key), a.value, b.value, c.value, d.value " +
|
|
||||||
"FROM A a " +
|
|
||||||
"INNER JOIN B b ON a.key = b.key AND a.association.value = b.association.value " +
|
|
||||||
"RIGHT JOIN a.cAssociationByKey c ON a.key = c.key AND a.association.value = c.association.value " +
|
|
||||||
"INNER JOIN D d ON d.key = c.key AND d.association.value = c.association.value " +
|
|
||||||
"ORDER BY COALESCE(a.key, b.key, c.key, d.key) ASC", Tuple.class).getResultList();
|
|
||||||
|
|
||||||
assertEquals(3, resultList.size());
|
|
||||||
|
|
||||||
assertEquals("a", resultList.get(0).get(1));
|
|
||||||
assertEquals("d", resultList.get(0).get(2));
|
|
||||||
assertEquals("g", resultList.get(0).get(3));
|
|
||||||
assertEquals("k", resultList.get(0).get(4));
|
|
||||||
|
|
||||||
assertEquals("b", resultList.get(1).get(1));
|
|
||||||
assertEquals("e", resultList.get(1).get(2));
|
|
||||||
assertEquals("h", resultList.get(1).get(3));
|
|
||||||
assertEquals("l", resultList.get(1).get(4));
|
|
||||||
|
|
||||||
assertNull(resultList.get(2).get(1));
|
|
||||||
assertNull(resultList.get(2).get(2));
|
|
||||||
assertEquals("j", resultList.get(2).get(3));
|
|
||||||
assertEquals("m", resultList.get(2).get(4));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testJoinOrderWithRightJoinWithNonOptionalAssociationProjections() {
|
|
||||||
doInJPA( this::sessionFactory, em -> {
|
|
||||||
List<Tuple> resultList = em.createQuery("SELECT COALESCE(a.key, b.key, c.key, d.key), a.value, b.value, c.value, d.value " +
|
|
||||||
"FROM A a " +
|
|
||||||
"INNER JOIN B b ON a.key = b.key " +
|
|
||||||
"RIGHT JOIN C c ON a.key = c.key " +
|
|
||||||
"INNER JOIN D d ON d.key = c.key " +
|
|
||||||
"ORDER BY COALESCE(a.key, b.key, c.key, d.key) ASC", Tuple.class).getResultList();
|
|
||||||
|
|
||||||
assertEquals(3, resultList.size());
|
|
||||||
|
|
||||||
assertEquals("a", resultList.get(0).get(1));
|
|
||||||
assertEquals("d", resultList.get(0).get(2));
|
|
||||||
assertEquals("g", resultList.get(0).get(3));
|
|
||||||
assertEquals("k", resultList.get(0).get(4));
|
|
||||||
|
|
||||||
assertEquals("b", resultList.get(1).get(1));
|
|
||||||
assertEquals("e", resultList.get(1).get(2));
|
|
||||||
assertEquals("h", resultList.get(1).get(3));
|
|
||||||
assertEquals("l", resultList.get(1).get(4));
|
|
||||||
|
|
||||||
assertNull(resultList.get(2).get(1));
|
|
||||||
assertNull(resultList.get(2).get(2));
|
|
||||||
assertEquals("j", resultList.get(2).get(3));
|
|
||||||
assertEquals("m", resultList.get(2).get(4));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testJoinOrderWithRightNormalJoinWithNonOptionalAssociationProjections() {
|
|
||||||
doInJPA( this::sessionFactory, em -> {
|
|
||||||
List<Tuple> resultList = em.createQuery("SELECT COALESCE(a.key, b.key, c.key, d.key), a.value, b.value, c.value, d.value " +
|
|
||||||
"FROM A a " +
|
|
||||||
"INNER JOIN B b ON a.key = b.key " +
|
|
||||||
"RIGHT JOIN a.cAssociationByKey c ON a.key = c.key " +
|
|
||||||
"INNER JOIN D d ON d.key = c.key " +
|
|
||||||
"ORDER BY COALESCE(a.key, b.key, c.key, d.key) ASC", Tuple.class).getResultList();
|
|
||||||
|
|
||||||
assertEquals(3, resultList.size());
|
|
||||||
|
|
||||||
assertEquals("a", resultList.get(0).get(1));
|
|
||||||
assertEquals("d", resultList.get(0).get(2));
|
|
||||||
assertEquals("g", resultList.get(0).get(3));
|
|
||||||
assertEquals("k", resultList.get(0).get(4));
|
|
||||||
|
|
||||||
assertEquals("b", resultList.get(1).get(1));
|
|
||||||
assertEquals("e", resultList.get(1).get(2));
|
|
||||||
assertEquals("h", resultList.get(1).get(3));
|
|
||||||
assertEquals("l", resultList.get(1).get(4));
|
|
||||||
|
|
||||||
assertNull(resultList.get(2).get(1));
|
|
||||||
assertNull(resultList.get(2).get(2));
|
|
||||||
assertEquals("j", resultList.get(2).get(3));
|
|
||||||
assertEquals("m", resultList.get(2).get(4));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
Loading…
Reference in New Issue