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 {
|
public Query setParameter(int position, Object val) throws HibernateException {
|
||||||
if ( val == null ) {
|
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 {
|
else {
|
||||||
setParameter( position, val, determineType( position, val ) );
|
setParameter( position, val, determineType( position, val ) );
|
||||||
|
@ -530,7 +534,7 @@ public abstract class AbstractQueryImpl implements Query {
|
||||||
return guessType( clazz );
|
return guessType( clazz );
|
||||||
}
|
}
|
||||||
|
|
||||||
private Type guessType(Class clazz) throws HibernateException {
|
public Type guessType(Class clazz) throws HibernateException {
|
||||||
String typename = clazz.getName();
|
String typename = clazz.getName();
|
||||||
Type type = session.getFactory().getTypeResolver().heuristicType( typename );
|
Type type = session.getFactory().getTypeResolver().heuristicType( typename );
|
||||||
boolean serializable = type != null && type instanceof SerializableType;
|
boolean serializable = type != null && type instanceof SerializableType;
|
||||||
|
|
|
@ -22,6 +22,7 @@ import org.hibernate.Session;
|
||||||
import org.hibernate.Transaction;
|
import org.hibernate.Transaction;
|
||||||
import org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl;
|
import org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl;
|
||||||
import org.hibernate.cfg.Configuration;
|
import org.hibernate.cfg.Configuration;
|
||||||
|
import org.hibernate.dialect.Oracle8iDialect;
|
||||||
import org.hibernate.dialect.PostgreSQL81Dialect;
|
import org.hibernate.dialect.PostgreSQL81Dialect;
|
||||||
import org.hibernate.dialect.PostgreSQLDialect;
|
import org.hibernate.dialect.PostgreSQLDialect;
|
||||||
import org.hibernate.dialect.function.SQLFunction;
|
import org.hibernate.dialect.function.SQLFunction;
|
||||||
|
@ -29,10 +30,13 @@ import org.hibernate.stat.Statistics;
|
||||||
|
|
||||||
import org.hibernate.testing.FailureExpected;
|
import org.hibernate.testing.FailureExpected;
|
||||||
import org.hibernate.testing.SkipForDialect;
|
import org.hibernate.testing.SkipForDialect;
|
||||||
|
import org.hibernate.testing.TestForIssue;
|
||||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||||
import org.hibernate.test.annotations.A320;
|
import org.hibernate.test.annotations.A320;
|
||||||
import org.hibernate.test.annotations.A320b;
|
import org.hibernate.test.annotations.A320b;
|
||||||
import org.hibernate.test.annotations.Plane;
|
import org.hibernate.test.annotations.Plane;
|
||||||
|
import org.hibernate.type.StandardBasicTypes;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
@ -92,6 +96,174 @@ public class QueryAndSQLTest extends BaseCoreFunctionalTestCase {
|
||||||
s.close();
|
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
|
@Test
|
||||||
public void testPackageQueries() throws Exception {
|
public void testPackageQueries() throws Exception {
|
||||||
Session s = openSession();
|
Session s = openSession();
|
||||||
|
|
|
@ -28,12 +28,10 @@ import org.hibernate.HibernateException;
|
||||||
import org.hibernate.LockMode;
|
import org.hibernate.LockMode;
|
||||||
import org.hibernate.SQLQuery;
|
import org.hibernate.SQLQuery;
|
||||||
import org.hibernate.TypeMismatchException;
|
import org.hibernate.TypeMismatchException;
|
||||||
import org.hibernate.engine.query.spi.HQLQueryPlan;
|
|
||||||
import org.hibernate.engine.query.spi.NamedParameterDescriptor;
|
import org.hibernate.engine.query.spi.NamedParameterDescriptor;
|
||||||
import org.hibernate.engine.query.spi.OrdinalParameterDescriptor;
|
import org.hibernate.engine.query.spi.OrdinalParameterDescriptor;
|
||||||
import org.hibernate.engine.query.spi.ParameterMetadata;
|
import org.hibernate.engine.query.spi.ParameterMetadata;
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
import org.hibernate.engine.spi.SessionImplementor;
|
|
||||||
import org.hibernate.hql.internal.QueryExecutionRequestException;
|
import org.hibernate.hql.internal.QueryExecutionRequestException;
|
||||||
import org.hibernate.internal.SQLQueryImpl;
|
import org.hibernate.internal.SQLQueryImpl;
|
||||||
import org.hibernate.jpa.AvailableSettings;
|
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.internal.util.LockModeTypeHelper;
|
||||||
import org.hibernate.jpa.spi.AbstractEntityManagerImpl;
|
import org.hibernate.jpa.spi.AbstractEntityManagerImpl;
|
||||||
import org.hibernate.jpa.spi.AbstractQueryImpl;
|
import org.hibernate.jpa.spi.AbstractQueryImpl;
|
||||||
|
import org.hibernate.jpa.spi.NullTypeBindableParameterRegistration;
|
||||||
import org.hibernate.jpa.spi.ParameterBind;
|
import org.hibernate.jpa.spi.ParameterBind;
|
||||||
import org.hibernate.jpa.spi.ParameterRegistration;
|
import org.hibernate.jpa.spi.ParameterRegistration;
|
||||||
import org.hibernate.type.CompositeCustomType;
|
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 static class ParameterRegistrationImpl<T> implements NullTypeBindableParameterRegistration<T> {
|
||||||
private final Query jpaQuery;
|
private final QueryImpl jpaQuery;
|
||||||
private final org.hibernate.Query nativeQuery;
|
private final org.hibernate.Query nativeQuery;
|
||||||
|
|
||||||
private final String name;
|
private final String name;
|
||||||
|
@ -170,7 +169,7 @@ public class QueryImpl<X> extends AbstractQueryImpl<X>
|
||||||
private ParameterBind<T> bind;
|
private ParameterBind<T> bind;
|
||||||
|
|
||||||
protected ParameterRegistrationImpl(
|
protected ParameterRegistrationImpl(
|
||||||
Query jpaQuery,
|
QueryImpl jpaQuery,
|
||||||
org.hibernate.Query nativeQuery,
|
org.hibernate.Query nativeQuery,
|
||||||
String name,
|
String name,
|
||||||
Class<T> javaType) {
|
Class<T> javaType) {
|
||||||
|
@ -182,7 +181,7 @@ public class QueryImpl<X> extends AbstractQueryImpl<X>
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ParameterRegistrationImpl(
|
protected ParameterRegistrationImpl(
|
||||||
Query jpaQuery,
|
QueryImpl jpaQuery,
|
||||||
org.hibernate.Query nativeQuery,
|
org.hibernate.Query nativeQuery,
|
||||||
Integer position,
|
Integer position,
|
||||||
Class<T> javaType) {
|
Class<T> javaType) {
|
||||||
|
@ -314,6 +313,41 @@ public class QueryImpl<X> extends AbstractQueryImpl<X>
|
||||||
public ParameterBind<T> getBind() {
|
public ParameterBind<T> getBind() {
|
||||||
return bind;
|
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;
|
final Integer position;
|
||||||
|
|
||||||
protected JpaPositionalParameterRegistrationImpl(
|
protected JpaPositionalParameterRegistrationImpl(
|
||||||
Query jpaQuery,
|
QueryImpl jpaQuery,
|
||||||
org.hibernate.Query nativeQuery,
|
org.hibernate.Query nativeQuery,
|
||||||
Integer position,
|
Integer position,
|
||||||
Class<T> javaType) {
|
Class<T> javaType) {
|
||||||
|
|
|
@ -545,7 +545,41 @@ public abstract class BaseQueryImpl implements Query {
|
||||||
checkOpen( true );
|
checkOpen( true );
|
||||||
|
|
||||||
try {
|
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) {
|
catch (QueryParameterException e) {
|
||||||
entityManager().markForRollbackOnly();
|
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 name;
|
||||||
private String descr;
|
private String descr;
|
||||||
|
private Integer intVal;
|
||||||
private Set<Distributor> distributors = new HashSet<Distributor>();
|
private Set<Distributor> distributors = new HashSet<Distributor>();
|
||||||
|
|
||||||
public Item() {
|
public Item() {
|
||||||
|
@ -98,6 +99,13 @@ public class Item implements Serializable {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Integer getIntVal() {
|
||||||
|
return intVal;
|
||||||
|
}
|
||||||
|
public void setIntVal(Integer intVal) {
|
||||||
|
this.intVal = intVal;
|
||||||
|
}
|
||||||
|
|
||||||
@OneToMany
|
@OneToMany
|
||||||
public Set<Distributor> getDistributors() {
|
public Set<Distributor> getDistributors() {
|
||||||
return distributors;
|
return distributors;
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.jpa.test.query;
|
package org.hibernate.jpa.test.query;
|
||||||
|
|
||||||
import java.sql.Timestamp;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
@ -19,6 +18,7 @@ import org.junit.Test;
|
||||||
|
|
||||||
import org.hibernate.Hibernate;
|
import org.hibernate.Hibernate;
|
||||||
import org.hibernate.cfg.AvailableSettings;
|
import org.hibernate.cfg.AvailableSettings;
|
||||||
|
import org.hibernate.dialect.Oracle8iDialect;
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
|
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
|
||||||
import org.hibernate.jpa.test.Distributor;
|
import org.hibernate.jpa.test.Distributor;
|
||||||
|
@ -28,6 +28,7 @@ import org.hibernate.stat.Statistics;
|
||||||
|
|
||||||
import junit.framework.Assert;
|
import junit.framework.Assert;
|
||||||
|
|
||||||
|
import org.hibernate.testing.SkipForDialect;
|
||||||
import org.hibernate.testing.TestForIssue;
|
import org.hibernate.testing.TestForIssue;
|
||||||
|
|
||||||
import static junit.framework.Assert.assertNull;
|
import static junit.framework.Assert.assertNull;
|
||||||
|
@ -79,7 +80,7 @@ public class QueryTest extends BaseEntityManagerFunctionalTestCase {
|
||||||
catch (IllegalArgumentException expected) {
|
catch (IllegalArgumentException expected) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testPagedQuery() throws Exception {
|
public void testPagedQuery() throws Exception {
|
||||||
EntityManager em = getOrCreateEntityManager();
|
EntityManager em = getOrCreateEntityManager();
|
||||||
|
@ -100,6 +101,341 @@ public class QueryTest extends BaseEntityManagerFunctionalTestCase {
|
||||||
em.close();
|
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
|
@Test
|
||||||
public void testAggregationReturnType() throws Exception {
|
public void testAggregationReturnType() throws Exception {
|
||||||
EntityManager em = getOrCreateEntityManager();
|
EntityManager em = getOrCreateEntityManager();
|
||||||
|
|
Loading…
Reference in New Issue