HHH-9230 - NullPointer when combining JPQL query with in clause and @NamedEntityGraph

This commit is contained in:
Steve Ebersole 2015-10-29 09:52:53 -05:00
parent 9390062abc
commit 287a516760
3 changed files with 116 additions and 14 deletions

View File

@ -33,6 +33,7 @@ import org.hibernate.Query;
import org.hibernate.QueryException;
import org.hibernate.Session;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.query.spi.EntityGraphQueryHint;
import org.hibernate.engine.query.spi.HQLQueryPlan;
import org.hibernate.engine.query.spi.ParameterMetadata;
import org.hibernate.engine.spi.QueryParameters;
@ -1026,11 +1027,25 @@ public abstract class AbstractQueryImpl implements Query {
}
}
public HQLQueryPlan getQueryPlan() {
return queryPlan;
}
public void setQueryPlan(HQLQueryPlan queryPlan) {
this.queryPlan = queryPlan;
/**
* Used from HEM code as a (hopefully temporary) means to apply a custom query plan
* in regards to a JPA entity graph.
*
* @param hint The entity graph hint object
*/
public void applyEntityGraphQueryHint(EntityGraphQueryHint hint) {
verifyParameters();
// todo : likely need to update the instance state related to queryString and parameters
final Map namedParams = getNamedParams();
final String expandedQuery = expandParameterLists( namedParams );
this.queryPlan = new HQLQueryPlan(
expandedQuery,
false,
session.getLoadQueryInfluencers().getEnabledFilters(),
session.getFactory(),
hint
);
}
}

View File

@ -553,16 +553,8 @@ public class QueryImpl<X> extends AbstractQueryImpl<X>
private List<X> list() {
if ( getEntityGraphQueryHint() != null ) {
SessionImplementor sessionImpl = (SessionImplementor) getEntityManager().getSession();
HQLQueryPlan entityGraphQueryPlan = new HQLQueryPlan(
getHibernateQuery().getQueryString(),
false,
sessionImpl.getLoadQueryInfluencers().getEnabledFilters(),
sessionImpl.getFactory(),
getEntityGraphQueryHint()
);
// Safe to assume QueryImpl at this point.
unwrap( org.hibernate.internal.QueryImpl.class ).setQueryPlan( entityGraphQueryPlan );
unwrap( org.hibernate.internal.QueryImpl.class ).applyEntityGraphQueryHint( getEntityGraphQueryHint() );
}
return query.list();
}

View File

@ -0,0 +1,95 @@
/*
* 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.jpa.test.query;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Entity;
import javax.persistence.EntityManager;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.NamedAttributeNode;
import javax.persistence.NamedEntityGraph;
import javax.persistence.Table;
import javax.persistence.TypedQuery;
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
import org.hibernate.testing.TestForIssue;
import org.junit.Test;
/**
* Based on the test developed by Hans Desmet to reproduce the bug reported in HHH-9230
*
* @author Steve Ebersole
*/
@TestForIssue(jiraKey = "HHH-9230")
public class QueryWithInParamListAndNamedEntityGraphTest extends BaseEntityManagerFunctionalTestCase {
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class[] {Person.class};
}
@Test
public void testInClause() {
// this test works
EntityManager em = getOrCreateEntityManager();
em.getTransaction().begin();
Set<Long> ids = new HashSet<Long>();
ids.add( 1L );
ids.add( 2L );
TypedQuery<Person> query = em.createQuery( "select p from Person p where p.id in :ids", Person.class );
query.setParameter( "ids", ids );
query.getResultList();
em.getTransaction().commit();
em.close();
}
@Test
public void testEntityGraph() {
// this test works
EntityManager em = getOrCreateEntityManager();
em.getTransaction().begin();
TypedQuery<Person> query = em.createQuery( "select p from Person p", Person.class );
query.setHint( "javax.persistence.loadgraph", em.createEntityGraph( "withBoss" ) );
query.getResultList();
em.getTransaction().commit();
em.close();
}
@Test
public void testEntityGraphAndInClause() {
// this test fails
EntityManager em = getOrCreateEntityManager();
em.getTransaction().begin();
Set<Long> ids = new HashSet<Long>();
ids.add( 1L );
ids.add( 2L );
TypedQuery<Person> query = em.createQuery( "select p from Person p where p.id in :ids", Person.class );
query.setHint( "javax.persistence.loadgraph", em.createEntityGraph( "withBoss" ) );
query.setParameter( "ids", ids );
query.getResultList();
em.getTransaction().commit();
em.close();
}
@Entity(name = "Person")
@Table(name = "Person")
@NamedEntityGraph(name = "withBoss", attributeNodes = @NamedAttributeNode("boss"))
public static class Person {
@Id
@GeneratedValue
private long id;
private String name;
@ManyToOne
@JoinColumn
private Person boss;
}
}