HHH-10161 : Hibernate ignores return value from javax.persistence.Parameter#getParameterType()
(cherry picked from commit b4dbb90f17
)
This commit is contained in:
parent
0280fe6d2a
commit
d3d88cfa67
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue