Fix Subquery#getCorrelatedJoins throws NPE when FromClause is null

This commit is contained in:
Andrea Boriero 2022-01-26 13:14:00 +01:00 committed by Steve Ebersole
parent b9d4a74693
commit cb6be7dc81
2 changed files with 112 additions and 1 deletions

View File

@ -48,6 +48,7 @@ import org.hibernate.query.sqm.tree.expression.SqmExpression;
import org.hibernate.query.sqm.tree.from.SqmAttributeJoin;
import org.hibernate.query.sqm.tree.from.SqmCrossJoin;
import org.hibernate.query.sqm.tree.from.SqmEntityJoin;
import org.hibernate.query.sqm.tree.from.SqmFromClause;
import org.hibernate.query.sqm.tree.from.SqmJoin;
import org.hibernate.query.sqm.tree.from.SqmRoot;
import org.hibernate.query.sqm.tree.predicate.SqmInPredicate;
@ -254,7 +255,12 @@ public class SqmSubQuery<T> extends AbstractSqmSelectQuery<T> implements SqmSele
@Override
public Set<Join<?, ?>> getCorrelatedJoins() {
final Set<Join<?, ?>> correlatedJoins = new HashSet<>();
for ( SqmRoot<?> root : getQuerySpec().getFromClause().getRoots() ) {
final SqmFromClause fromClause = getQuerySpec().getFromClause();
if ( fromClause == null ) {
return correlatedJoins;
}
for ( SqmRoot<?> root : fromClause.getRoots() ) {
if ( root instanceof SqmCorrelation<?, ?> ) {
for ( SqmJoin<?, ?> sqmJoin : root.getSqmJoins() ) {
if ( sqmJoin instanceof SqmCorrelation<?, ?> && sqmJoin instanceof Join<?, ?> ) {

View File

@ -0,0 +1,105 @@
/*
* 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.Collection;
import java.util.Set;
import org.hibernate.testing.orm.junit.EntityManagerFactoryScope;
import org.hibernate.testing.orm.junit.Jpa;
import org.junit.jupiter.api.Test;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.OneToMany;
import jakarta.persistence.Table;
import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.CriteriaQuery;
import jakarta.persistence.criteria.Join;
import jakarta.persistence.criteria.Root;
import jakarta.persistence.criteria.Subquery;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
@Jpa(
annotatedClasses = {
CriteriaGetCorrelatedJoinsTest.Person.class,
CriteriaGetCorrelatedJoinsTest.Address.class
}
)
public class CriteriaGetCorrelatedJoinsTest {
@Test
public void testGetCorrelatedJoins(EntityManagerFactoryScope scope) {
scope.inEntityManager(
entityManager -> {
final CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
final CriteriaQuery<Person> query = criteriaBuilder.createQuery( Person.class );
final Root<Person> person = query.from( Person.class );
query.select( person );
final Subquery<Address> subquery = query.subquery( Address.class );
Set<Join<?, ?>> correlatedJoins = subquery.getCorrelatedJoins();
assertNotNull( correlatedJoins );
assertEquals( 0, correlatedJoins.size() );
final Join<Person, Address> sqo = subquery
.correlate( person.join( person.getModel().getCollection( "addresses", Address.class ) ) );
subquery.select( sqo );
correlatedJoins = subquery.getCorrelatedJoins();
assertNotNull( correlatedJoins );
assertEquals( 1, correlatedJoins.size() );
}
);
}
@Entity(name = "Person")
@Table(name = "PERSON_TABLE")
public static class Person {
@Id
private Integer id;
private String name;
private Integer age;
Person() {
}
public Person(Integer id, String name, Integer age) {
this.id = id;
this.name = name;
this.age = age;
}
@OneToMany
private Collection<Address> addresses;
}
@Entity(name = "Address")
@Table(name = "ADDRESS_TABLE")
public static class Address {
@Id
private Integer id;
private String street;
private String city;
public Address(Integer id, String street, String city) {
this.id = id;
this.street = street;
this.city = city;
}
}
}