HHH-10161 : Hibernate ignores return value from javax.persistence.Parameter#getParameterType()

(cherry picked from commit b4dbb90f17)
This commit is contained in:
Gail Badner 2015-10-22 12:26:42 -07:00 committed by Steve Ebersole
parent 0280fe6d2a
commit d3d88cfa67
7 changed files with 629 additions and 12 deletions

View File

@ -463,7 +463,11 @@ public abstract class AbstractQueryImpl implements Query {
public Query setParameter(int position, Object val) throws HibernateException {
if ( val == null ) {
setParameter( position, val, StandardBasicTypes.SERIALIZABLE );
Type type = parameterMetadata.getOrdinalParameterDescriptor( position + 1 ).getExpectedType();
if ( type == null ) {
type = StandardBasicTypes.SERIALIZABLE;
}
setParameter( position, val, type );
}
else {
setParameter( position, val, determineType( position, val ) );
@ -530,7 +534,7 @@ public abstract class AbstractQueryImpl implements Query {
return guessType( clazz );
}
private Type guessType(Class clazz) throws HibernateException {
public Type guessType(Class clazz) throws HibernateException {
String typename = clazz.getName();
Type type = session.getFactory().getTypeResolver().heuristicType( typename );
boolean serializable = type != null && type instanceof SerializableType;

View File

@ -22,6 +22,7 @@ import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl;
import org.hibernate.cfg.Configuration;
import org.hibernate.dialect.Oracle8iDialect;
import org.hibernate.dialect.PostgreSQL81Dialect;
import org.hibernate.dialect.PostgreSQLDialect;
import org.hibernate.dialect.function.SQLFunction;
@ -29,10 +30,13 @@ import org.hibernate.stat.Statistics;
import org.hibernate.testing.FailureExpected;
import org.hibernate.testing.SkipForDialect;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
import org.hibernate.test.annotations.A320;
import org.hibernate.test.annotations.A320b;
import org.hibernate.test.annotations.Plane;
import org.hibernate.type.StandardBasicTypes;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
@ -92,6 +96,174 @@ public class QueryAndSQLTest extends BaseCoreFunctionalTestCase {
s.close();
}
@Test
@TestForIssue( jiraKey = "HHH-10161")
@SkipForDialect(
value = Oracle8iDialect.class,
jiraKey = "HHH-10161",
comment = "Oracle cannot convert untyped null (assumed to be BINARY type) to NUMBER")
public void testQueryWithNullParameter(){
Chaos c0 = new Chaos();
c0.setId( 0L );
c0.setName( "c0" );
c0.setSize( 0L );
Chaos c1 = new Chaos();
c1.setId( 1L );
c1.setName( "c1" );
c1.setSize( 1L );
Chaos c2 = new Chaos();
c2.setId( 2L );
c2.setName( "c2" );
c2.setSize( null );
Session s = openSession();
s.beginTransaction();
s.persist( c0 );
s.persist( c1 );
s.persist( c2 );
s.flush();
s.clear();
List chaoses = s.createQuery( "from Chaos where chaos_size is null or chaos_size = :chaos_size" )
.setParameter( "chaos_size", null )
.list();
assertEquals( 1, chaoses.size() );
chaoses = s.createQuery( "from Chaos where chaos_size = :chaos_size" )
.setParameter( "chaos_size", null )
.list();
// should be no results because null != null
assertEquals( 0, chaoses.size() );
s.getTransaction().rollback();
s.close();
}
@Test
@TestForIssue( jiraKey = "HHH-10161")
public void testQueryWithNullParameterTyped(){
Chaos c0 = new Chaos();
c0.setId( 0L );
c0.setName( "c0" );
c0.setSize( 0L );
Chaos c1 = new Chaos();
c1.setId( 1L );
c1.setName( "c1" );
c1.setSize( 1L );
Chaos c2 = new Chaos();
c2.setId( 2L );
c2.setName( "c2" );
c2.setSize( null );
Session s = openSession();
s.beginTransaction();
s.persist( c0 );
s.persist( c1 );
s.persist( c2 );
s.flush();
s.clear();
List chaoses = s.createQuery( "from Chaos where chaos_size is null or chaos_size = :chaos_size" )
.setParameter( "chaos_size", null, StandardBasicTypes.LONG )
.list();
assertEquals( 1, chaoses.size() );
chaoses = s.createQuery( "from Chaos where chaos_size = :chaos_size" )
.setParameter( "chaos_size", null, StandardBasicTypes.LONG )
.list();
// should be no results because null != null
assertEquals( 0, chaoses.size() );
s.getTransaction().rollback();
s.close();
}
@Test
@TestForIssue( jiraKey = "HHH-10161")
@SkipForDialect(
value = Oracle8iDialect.class,
jiraKey = "HHH-10161",
comment = "Oracle cannot convert untyped null (assumed to be BINARY type) to NUMBER")
public void testNativeQueryWithNullParameter(){
Chaos c0 = new Chaos();
c0.setId( 0L );
c0.setName( "c0" );
c0.setSize( 0L );
Chaos c1 = new Chaos();
c1.setId( 1L );
c1.setName( "c1" );
c1.setSize( 1L );
Chaos c2 = new Chaos();
c2.setId( 2L );
c2.setName( "c2" );
c2.setSize( null );
Session s = openSession();
s.beginTransaction();
s.persist( c0 );
s.persist( c1 );
s.persist( c2 );
s.flush();
s.clear();
List chaoses = s.createSQLQuery( "select * from Chaos where chaos_size is null or chaos_size = :chaos_size" )
.setParameter( "chaos_size", null )
.list();
assertEquals( 1, chaoses.size() );
chaoses = s.createSQLQuery( "select * from Chaos where chaos_size = :chaos_size" )
.setParameter( "chaos_size", null )
.list();
// should be no results because null != null
assertEquals( 0, chaoses.size() );
s.getTransaction().rollback();
s.close();
}
@Test
@TestForIssue( jiraKey = "HHH-10161")
public void testNativeQueryWithNullParameterTyped(){
Chaos c0 = new Chaos();
c0.setId( 0L );
c0.setName( "c0" );
c0.setSize( 0L );
Chaos c1 = new Chaos();
c1.setId( 1L );
c1.setName( "c1" );
c1.setSize( 1L );
Chaos c2 = new Chaos();
c2.setId( 2L );
c2.setName( "c2" );
c2.setSize( null );
Session s = openSession();
s.beginTransaction();
s.persist( c0 );
s.persist( c1 );
s.persist( c2 );
s.flush();
s.clear();
List chaoses = s.createSQLQuery( "select * from Chaos where chaos_size is null or chaos_size = :chaos_size" )
.setParameter( "chaos_size", null, StandardBasicTypes.LONG )
.list();
assertEquals( 1, chaoses.size() );
chaoses = s.createSQLQuery( "select * from Chaos where chaos_size = :chaos_size" )
.setParameter( "chaos_size", null, StandardBasicTypes.LONG )
.list();
// should be no results because null != null
assertEquals( 0, chaoses.size() );
s.getTransaction().rollback();
s.close();
}
@Test
public void testPackageQueries() throws Exception {
Session s = openSession();

View File

@ -28,12 +28,10 @@ import org.hibernate.HibernateException;
import org.hibernate.LockMode;
import org.hibernate.SQLQuery;
import org.hibernate.TypeMismatchException;
import org.hibernate.engine.query.spi.HQLQueryPlan;
import org.hibernate.engine.query.spi.NamedParameterDescriptor;
import org.hibernate.engine.query.spi.OrdinalParameterDescriptor;
import org.hibernate.engine.query.spi.ParameterMetadata;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.hql.internal.QueryExecutionRequestException;
import org.hibernate.internal.SQLQueryImpl;
import org.hibernate.jpa.AvailableSettings;
@ -42,6 +40,7 @@ import org.hibernate.jpa.internal.util.ConfigurationHelper;
import org.hibernate.jpa.internal.util.LockModeTypeHelper;
import org.hibernate.jpa.spi.AbstractEntityManagerImpl;
import org.hibernate.jpa.spi.AbstractQueryImpl;
import org.hibernate.jpa.spi.NullTypeBindableParameterRegistration;
import org.hibernate.jpa.spi.ParameterBind;
import org.hibernate.jpa.spi.ParameterRegistration;
import org.hibernate.type.CompositeCustomType;
@ -159,8 +158,8 @@ public class QueryImpl<X> extends AbstractQueryImpl<X>
}
}
private static class ParameterRegistrationImpl<T> implements ParameterRegistration<T> {
private final Query jpaQuery;
private static class ParameterRegistrationImpl<T> implements NullTypeBindableParameterRegistration<T> {
private final QueryImpl jpaQuery;
private final org.hibernate.Query nativeQuery;
private final String name;
@ -170,7 +169,7 @@ public class QueryImpl<X> extends AbstractQueryImpl<X>
private ParameterBind<T> bind;
protected ParameterRegistrationImpl(
Query jpaQuery,
QueryImpl jpaQuery,
org.hibernate.Query nativeQuery,
String name,
Class<T> javaType) {
@ -182,7 +181,7 @@ public class QueryImpl<X> extends AbstractQueryImpl<X>
}
protected ParameterRegistrationImpl(
Query jpaQuery,
QueryImpl jpaQuery,
org.hibernate.Query nativeQuery,
Integer position,
Class<T> javaType) {
@ -314,6 +313,41 @@ public class QueryImpl<X> extends AbstractQueryImpl<X>
public ParameterBind<T> getBind() {
return bind;
}
@Override
public void bindNullValue(Class<?> nullParameterType) {
if ( nullParameterType == null ) {
throw new IllegalArgumentException( "nullParameterType must be non-null" );
}
if ( getParameterType() != null ) {
throw new IllegalArgumentException(
String.format(
"Cannot bind null value as type [%s]; it is already mapped as type [%s]",
nullParameterType.getName(),
getParameterType().getName()
)
);
}
validateBinding( nullParameterType, null, null );
if ( !org.hibernate.internal.AbstractQueryImpl.class.isInstance( jpaQuery.getHibernateQuery() ) ) {
throw new IllegalStateException(
"Unknown query type for binding null value" + jpaQuery.getHibernateQuery()
.getClass()
.getName()
);
}
org.hibernate.internal.AbstractQueryImpl abstractQuery =
(org.hibernate.internal.AbstractQueryImpl) jpaQuery.getHibernateQuery();
final Type explicitType = abstractQuery.guessType( nullParameterType );
if ( name != null ) {
nativeQuery.setParameter( name, null, explicitType );
}
else {
nativeQuery.setParameter( position - 1, null, explicitType );
}
bind = new ParameterBindImpl<T>( null, null );
}
}
/**
@ -325,7 +359,7 @@ public class QueryImpl<X> extends AbstractQueryImpl<X>
final Integer position;
protected JpaPositionalParameterRegistrationImpl(
Query jpaQuery,
QueryImpl jpaQuery,
org.hibernate.Query nativeQuery,
Integer position,
Class<T> javaType) {

View File

@ -545,7 +545,41 @@ public abstract class BaseQueryImpl implements Query {
checkOpen( true );
try {
findParameterRegistration( param ).bindValue( value );
final ParameterRegistration<T> parameterRegistrationExisting = findParameterRegistration( param );
if ( value == null
&& param.getParameterType() != null
&& parameterRegistrationExisting.getParameterType() == null &&
NullTypeBindableParameterRegistration.class.isInstance( parameterRegistrationExisting ) ) {
// we have:
// 1) a null value to bind;
// 2) parameterRegistrationExisting has no information about the Java type for that null value;
// 3) parameter.getParameterType() supplies a non-null parameter type;
// NOTE: According to Javadoc for javax.persistenceParameter#getParameterType:
// "Applications that use this method for Java Persistence query language
// queries and native queries will not be portable."
// and 4) parameterRegistrationExisting allows for overriding the null parameter type when
// binding a null value;
( (NullTypeBindableParameterRegistration) parameterRegistrationExisting ).bindNullValue( param.getParameterType() );
}
else {
// NOTE: The Javadoc for javax.persistence.Query#setParameter(Parameter<T> param, T value)
// does not say anything about throwing IllegalArgumentException if
// javax.persistenceParameter#getParameterType is not assignable to the type, so we simply log
// a message if this is the case.
if ( param.getParameterType() != null &&
parameterRegistrationExisting.getParameterType() != null &&
!parameterRegistrationExisting.getParameterType().isAssignableFrom( param.getParameterType() ) ) {
LOG.warnf(
"Parameter type [%s] is not assignment compatible with requested type [%s] for parameter %s",
parameterRegistrationExisting.getParameterType().getName(),
param.getParameterType().getName(),
parameterRegistrationExisting.getName() == null ?
"at position [" + param.getPosition() + "]" :
"named [" + parameterRegistrationExisting.getName() + "]"
);
}
parameterRegistrationExisting.bindValue( value );
}
}
catch (QueryParameterException e) {
entityManager().markForRollbackOnly();

View File

@ -0,0 +1,29 @@
/*
* 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.spi;
/**
* A {@link ParameterRegistration} that allows providing Java type information when
* binding a null value for a parameter when there is no other available type information
* for that parameter.
*
* @author Gail Badner
*/
public interface NullTypeBindableParameterRegistration<T> extends ParameterRegistration<T> {
/**
* If bindable, bind a null value using the provided parameter type.
* This method is only valid if {@link #getParameterType} returns {@code null}.
*
* @param nullParameterType the Java type to be used for binding the null value;
* must be non-null.
*
* @throws IllegalArgumentException {@code parameterType} is null or if
* {@link #getParameterType} does not return null.
*/
public void bindNullValue(Class<?> nullParameterType);
}

View File

@ -69,6 +69,7 @@ public class Item implements Serializable {
private String name;
private String descr;
private Integer intVal;
private Set<Distributor> distributors = new HashSet<Distributor>();
public Item() {
@ -98,6 +99,13 @@ public class Item implements Serializable {
this.name = name;
}
public Integer getIntVal() {
return intVal;
}
public void setIntVal(Integer intVal) {
this.intVal = intVal;
}
@OneToMany
public Set<Distributor> getDistributors() {
return distributors;

View File

@ -6,7 +6,6 @@
*/
package org.hibernate.jpa.test.query;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
@ -19,6 +18,7 @@ import org.junit.Test;
import org.hibernate.Hibernate;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.dialect.Oracle8iDialect;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
import org.hibernate.jpa.test.Distributor;
@ -28,6 +28,7 @@ import org.hibernate.stat.Statistics;
import junit.framework.Assert;
import org.hibernate.testing.SkipForDialect;
import org.hibernate.testing.TestForIssue;
import static junit.framework.Assert.assertNull;
@ -79,7 +80,7 @@ public class QueryTest extends BaseEntityManagerFunctionalTestCase {
catch (IllegalArgumentException expected) {
}
}
@Test
public void testPagedQuery() throws Exception {
EntityManager em = getOrCreateEntityManager();
@ -100,6 +101,341 @@ public class QueryTest extends BaseEntityManagerFunctionalTestCase {
em.close();
}
@Test
public void testNullPositionalParameter() throws Exception {
EntityManager em = getOrCreateEntityManager();
em.getTransaction().begin();
Item item = new Item( "Mouse", "Micro$oft mouse" );
em.persist( item );
Query q = em.createQuery( "from Item i where i.intVal=?" );
q.setParameter( 1, null );
List results = q.getResultList();
// null != null
assertEquals( 0, results.size() );
q = em.createQuery( "from Item i where i.intVal is null and ? is null" );
q.setParameter( 1, null );
results = q.getResultList();
assertEquals( 1, results.size() );
q = em.createQuery( "from Item i where i.intVal is null or i.intVal = ?" );
q.setParameter( 1, null );
results = q.getResultList();
assertEquals( 1, results.size() );
em.getTransaction().rollback();
em.close();
}
@Test
public void testNullPositionalParameterParameter() throws Exception {
EntityManager em = getOrCreateEntityManager();
em.getTransaction().begin();
Item item = new Item( "Mouse", "Micro$oft mouse" );
em.persist( item );
Query q = em.createQuery( "from Item i where i.intVal=?" );
Parameter p = new Parameter() {
@Override
public String getName() {
return null;
}
@Override
public Integer getPosition() {
return 1;
}
@Override
public Class getParameterType() {
return Integer.class;
}
};
q.setParameter( p, null );
Parameter pGotten = q.getParameter( p.getPosition() );
List results = q.getResultList();
// null != null
assertEquals( 0, results.size() );
q = em.createQuery( "from Item i where i.intVal is null and ? is null" );
q.setParameter( p, null );
results = q.getResultList();
assertEquals( 1, results.size() );
q = em.createQuery( "from Item i where i.intVal is null or i.intVal = ?" );
q.setParameter( p, null );
results = q.getResultList();
assertEquals( 1, results.size() );
em.getTransaction().rollback();
em.close();
}
@Test
public void testNullPositionalParameterParameterIncompatible() throws Exception {
EntityManager em = getOrCreateEntityManager();
em.getTransaction().begin();
Item item = new Item( "Mouse", "Micro$oft mouse" );
em.persist( item );
Query q = em.createQuery( "from Item i where i.intVal=?" );
Parameter p = new Parameter() {
@Override
public String getName() {
return null;
}
@Override
public Integer getPosition() {
return 1;
}
@Override
public Class getParameterType() {
return Long.class;
}
};
q.setParameter( p, null );
Parameter pGotten = q.getParameter( p.getPosition() );
List results = q.getResultList();
// null != null
assertEquals( 0, results.size() );
q = em.createQuery( "from Item i where i.intVal is null and ? is null" );
q.setParameter( p, null );
results = q.getResultList();
assertEquals( 1, results.size() );
q = em.createQuery( "from Item i where i.intVal is null or i.intVal = ?" );
q.setParameter( p, null );
results = q.getResultList();
assertEquals( 1, results.size() );
em.getTransaction().rollback();
em.close();
}
@Test
public void testNullNamedParameter() throws Exception {
EntityManager em = getOrCreateEntityManager();
em.getTransaction().begin();
Item item = new Item( "Mouse", "Micro$oft mouse" );
em.persist( item );
Query q = em.createQuery( "from Item i where i.intVal=:iVal" );
q.setParameter( "iVal", null );
List results = q.getResultList();
// null != null
assertEquals( 0, results.size() );
q = em.createQuery( "from Item i where i.intVal is null and :iVal is null" );
q.setParameter( "iVal", null );
results = q.getResultList();
assertEquals( 1, results.size() );
q = em.createQuery( "from Item i where i.intVal is null or i.intVal = :iVal" );
q.setParameter( "iVal", null );
results = q.getResultList();
assertEquals( 1, results.size() );
em.getTransaction().rollback();
em.close();
}
@Test
public void testNullNamedParameterParameter() throws Exception {
EntityManager em = getOrCreateEntityManager();
em.getTransaction().begin();
Item item = new Item( "Mouse", "Micro$oft mouse" );
em.persist( item );
Query q = em.createQuery( "from Item i where i.intVal=:iVal" );
Parameter p = new Parameter() {
@Override
public String getName() {
return "iVal";
}
@Override
public Integer getPosition() {
return null;
}
@Override
public Class getParameterType() {
return Integer.class;
}
};
q.setParameter( p, null );
List results = q.getResultList();
// null != null
assertEquals( 0, results.size() );
q = em.createQuery( "from Item i where i.intVal is null and :iVal is null" );
q.setParameter( p, null );
results = q.getResultList();
assertEquals( 1, results.size() );
q = em.createQuery( "from Item i where i.intVal is null or i.intVal = :iVal" );
q.setParameter( p, null );
results = q.getResultList();
assertEquals( 1, results.size() );
em.getTransaction().rollback();
em.close();
}
@Test
public void testNullNamedParameterParameterIncompatible() throws Exception {
EntityManager em = getOrCreateEntityManager();
em.getTransaction().begin();
Item item = new Item( "Mouse", "Micro$oft mouse" );
em.persist( item );
Query q = em.createQuery( "from Item i where i.intVal=:iVal" );
Parameter p = new Parameter() {
@Override
public String getName() {
return "iVal";
}
@Override
public Integer getPosition() {
return null;
}
@Override
public Class getParameterType() {
return Long.class;
}
};
q.setParameter( p, null );
List results = q.getResultList();
// null != null
assertEquals( 0, results.size() );
q = em.createQuery( "from Item i where i.intVal is null and :iVal is null" );
q.setParameter( p, null );
results = q.getResultList();
assertEquals( 1, results.size() );
q = em.createQuery( "from Item i where i.intVal is null or i.intVal = :iVal" );
q.setParameter( p, null );
results = q.getResultList();
assertEquals( 1, results.size() );
em.getTransaction().rollback();
em.close();
}
@Test
@SkipForDialect(
value = Oracle8iDialect.class,
jiraKey = "HHH-10161",
comment = "Oracle cannot convert untyped null (assumed to be BINARY type) to NUMBER")
public void testNativeQueryNullPositionalParameter() throws Exception {
EntityManager em = getOrCreateEntityManager();
em.getTransaction().begin();
Item item = new Item( "Mouse", "Micro$oft mouse" );
em.persist( item );
// native queries don't seem to flush by default ?!?
em.flush();
Query q = em.createNativeQuery( "select * from Item i where i.intVal=?" );
q.setParameter( 1, null );
List results = q.getResultList();
// null != null
assertEquals( 0, results.size() );
q = em.createNativeQuery( "select * from Item i where i.intVal is null and ? is null" );
q.setParameter( 1, null );
results = q.getResultList();
assertEquals( 1, results.size() );
q = em.createNativeQuery( "select * from Item i where i.intVal is null or i.intVal = ?" );
q.setParameter( 1, null );
results = q.getResultList();
assertEquals( 1, results.size() );
em.getTransaction().rollback();
em.close();
}
@Test
@TestForIssue(jiraKey = "HHH-10161" )
public void testNativeQueryNullPositionalParameterParameter() throws Exception {
EntityManager em = getOrCreateEntityManager();
em.getTransaction().begin();
Item item = new Item( "Mouse", "Micro$oft mouse" );
em.persist( item );
// native queries don't seem to flush by default ?!?
em.flush();
Query q = em.createNativeQuery( "select * from Item i where i.intVal=?" );
Parameter p = new Parameter() {
@Override
public String getName() {
return null;
}
@Override
public Integer getPosition() {
return 1;
}
@Override
public Class getParameterType() {
return Integer.class;
}
};
q.setParameter( p, null );
Parameter pGotten = q.getParameter( p.getPosition() );
List results = q.getResultList();
// null != null
assertEquals( 0, results.size() );
q = em.createNativeQuery( "select * from Item i where i.intVal is null and ? is null" );
q.setParameter( p, null );
results = q.getResultList();
assertEquals( 1, results.size() );
q = em.createNativeQuery( "select * from Item i where i.intVal is null or i.intVal = ?" );
q.setParameter( p, null );
results = q.getResultList();
assertEquals( 1, results.size() );
em.getTransaction().rollback();
em.close();
}
@Test
@SkipForDialect(
value = Oracle8iDialect.class,
jiraKey = "HHH-10161",
comment = "Oracle cannot convert untyped null (assumed to be BINARY type) to NUMBER")
public void testNativeQueryNullNamedParameter() throws Exception {
EntityManager em = getOrCreateEntityManager();
em.getTransaction().begin();
Item item = new Item( "Mouse", "Micro$oft mouse" );
em.persist( item );
// native queries don't seem to flush by default ?!?
em.flush();
Query q = em.createNativeQuery( "select * from Item i where i.intVal=:iVal" );
q.setParameter( "iVal", null );
List results = q.getResultList();
// null != null
assertEquals( 0, results.size() );
q = em.createNativeQuery( "select * from Item i where (i.intVal is null) and (:iVal is null)" );
q.setParameter( "iVal", null );
results = q.getResultList();
assertEquals( 1, results.size() );
q = em.createNativeQuery( "select * from Item i where i.intVal is null or i.intVal = :iVal" );
q.setParameter( "iVal", null );
results = q.getResultList();
assertEquals( 1, results.size() );
em.getTransaction().rollback();
em.close();
}
@Test
@TestForIssue(jiraKey = "HHH-10161" )
public void testNativeQueryNullNamedParameterParameter() throws Exception {
EntityManager em = getOrCreateEntityManager();
em.getTransaction().begin();
Item item = new Item( "Mouse", "Micro$oft mouse" );
em.persist( item );
// native queries don't seem to flush by default ?!?
em.flush();
Query q = em.createNativeQuery( "select * from Item i where i.intVal=:iVal" );
Parameter p = new Parameter() {
@Override
public String getName() {
return "iVal";
}
@Override
public Integer getPosition() {
return null;
}
@Override
public Class getParameterType() {
return Integer.class;
}
};
q.setParameter( p, null );
Parameter pGotten = q.getParameter( p.getName() );
List results = q.getResultList();
assertEquals( 0, results.size() );
q = em.createNativeQuery( "select * from Item i where (i.intVal is null) and (:iVal is null)" );
q.setParameter( p, null );
results = q.getResultList();
assertEquals( 1, results.size() );
q = em.createNativeQuery( "select * from Item i where i.intVal is null or i.intVal = :iVal" );
q.setParameter( p, null );
results = q.getResultList();
assertEquals( 1, results.size() );
em.getTransaction().rollback();
em.close();
}
@Test
public void testAggregationReturnType() throws Exception {
EntityManager em = getOrCreateEntityManager();