HHH-15895 - IllegalArgumentException :Cannot create binding for parameter referencen with criteria builder
This commit is contained in:
parent
e65ded7a21
commit
7abc9f712c
|
@ -13,7 +13,6 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.query.internal.QueryParameterNamedImpl;
|
||||
import org.hibernate.query.internal.QueryParameterPositionalImpl;
|
||||
import org.hibernate.query.spi.QueryParameterImplementor;
|
||||
|
@ -21,9 +20,7 @@ import org.hibernate.query.sqm.SqmTreeTransformationLogger;
|
|||
import org.hibernate.query.sqm.tree.SqmStatement;
|
||||
import org.hibernate.query.sqm.tree.expression.JpaCriteriaParameter;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmJpaCriteriaParameterWrapper;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmNamedParameter;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmParameter;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmPositionalParameter;
|
||||
|
||||
/**
|
||||
* Maintains a cross-reference between SqmParameter and QueryParameter references.
|
||||
|
@ -32,8 +29,7 @@ import org.hibernate.query.sqm.tree.expression.SqmPositionalParameter;
|
|||
*/
|
||||
public class DomainParameterXref {
|
||||
/**
|
||||
* Create a DomainParameterXref for the parameters defined in the passed
|
||||
* SQM statement
|
||||
* Create a DomainParameterXref for the parameters defined in the SQM statement
|
||||
*/
|
||||
public static DomainParameterXref from(SqmStatement<?> sqmStatement) {
|
||||
// `xrefMap` is used to help maintain the proper cardinality between an
|
||||
|
@ -42,10 +38,7 @@ public class DomainParameterXref {
|
|||
// `.. where a.b = :param or a.c = :param`. Here we have 2 SqmParameter
|
||||
// references (one for each occurrence of `:param`) both of which map to
|
||||
// the same QueryParameter.
|
||||
final Map<SqmParameter, QueryParameterImplementor<?>> xrefMap = new TreeMap<>(
|
||||
(o1, o2) ->
|
||||
o1.compare( o2 )
|
||||
);
|
||||
final Map<SqmParameter<?>, QueryParameterImplementor<?>> xrefMap = new TreeMap<>();
|
||||
|
||||
final SqmStatement.ParameterResolutions parameterResolutions = sqmStatement.resolveParameters();
|
||||
if ( parameterResolutions.getSqmParameters().isEmpty() ) {
|
||||
|
|
|
@ -166,9 +166,9 @@ public class JpaCriteriaParameter<T>
|
|||
}
|
||||
|
||||
@Override
|
||||
public int compare(SqmParameter anotherParameter) {
|
||||
return anotherParameter instanceof JpaCriteriaParameter ?
|
||||
Integer.compare( hashCode(), anotherParameter.hashCode() )
|
||||
public int compareTo(SqmParameter anotherParameter) {
|
||||
return anotherParameter instanceof JpaCriteriaParameter
|
||||
? Integer.compare( hashCode(), anotherParameter.hashCode() )
|
||||
: 1;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -124,35 +124,9 @@ public class SqmJpaCriteriaParameterWrapper<T>
|
|||
}
|
||||
|
||||
@Override
|
||||
public int compare(SqmParameter anotherParameter) {
|
||||
public int compareTo(SqmParameter anotherParameter) {
|
||||
return anotherParameter instanceof SqmJpaCriteriaParameterWrapper ?
|
||||
getJpaCriteriaParameter().compare( ( (SqmJpaCriteriaParameterWrapper<?>) anotherParameter ).getJpaCriteriaParameter() )
|
||||
getJpaCriteriaParameter().compareTo( ( (SqmJpaCriteriaParameterWrapper<?>) anotherParameter ).getJpaCriteriaParameter() )
|
||||
: 1;
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public Expression toSqlExpression(
|
||||
// Clause clause,
|
||||
// SqmToSqlAstConverter walker,
|
||||
// SqlAstCreationState sqlAstCreationState) {
|
||||
//
|
||||
// final MappingModelExpressible mappingModelExpressible = DomainModelHelper.resolveMappingModelExpressible(
|
||||
// jpaCriteriaParameter,
|
||||
// sqlAstCreationState
|
||||
// );
|
||||
//
|
||||
// final List<JdbcMapping> jdbcMappings = mappingModelExpressible.getJdbcMappings(
|
||||
// sqlAstCreationState.getCreationContext().getDomainModel().getTypeConfiguration()
|
||||
// );
|
||||
//
|
||||
// if ( jdbcMappings.size() == 1 ) {
|
||||
// return new JdbcParameterImpl( jdbcMappings.get( 0 ) );
|
||||
// }
|
||||
//
|
||||
// final SqlTuple.Builder tupleBuilder = new SqlTuple.Builder( mappingModelExpressible );
|
||||
// for ( JdbcMapping jdbcMapping : jdbcMappings ) {
|
||||
// tupleBuilder.addSubExpression( new JdbcParameterImpl( jdbcMapping ) );
|
||||
// }
|
||||
// return tupleBuilder.buildTuple();
|
||||
// }
|
||||
}
|
||||
|
|
|
@ -83,7 +83,7 @@ public class SqmNamedParameter<T> extends AbstractSqmParameter<T> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public int compare(SqmParameter anotherParameter) {
|
||||
public int compareTo(SqmParameter anotherParameter) {
|
||||
return anotherParameter instanceof SqmNamedParameter<?>
|
||||
? getName().compareTo( ( (SqmNamedParameter<?>) anotherParameter ).getName() )
|
||||
: -1;
|
||||
|
|
|
@ -23,7 +23,7 @@ import org.hibernate.query.sqm.tree.SqmCopyContext;
|
|||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface SqmParameter<T> extends SqmExpression<T>, JpaParameterExpression<T> {
|
||||
public interface SqmParameter<T> extends SqmExpression<T>, JpaParameterExpression<T>, Comparable<SqmParameter<T>> {
|
||||
/**
|
||||
* If this represents a named parameter, return that parameter name;
|
||||
* otherwise return {@code null}.
|
||||
|
@ -76,20 +76,25 @@ public interface SqmParameter<T> extends SqmExpression<T>, JpaParameterExpressio
|
|||
@Override
|
||||
SqmParameter<T> copy(SqmCopyContext context);
|
||||
|
||||
default int compare(SqmParameter anotherParameter) {
|
||||
/**
|
||||
* @implSpec Defined as default since this is an SPI to
|
||||
* support any previous extensions
|
||||
*/
|
||||
@Override
|
||||
default int compareTo(SqmParameter<T> anotherParameter) {
|
||||
if ( this instanceof SqmNamedParameter ) {
|
||||
final SqmNamedParameter<?> one = (SqmNamedParameter<?>) this;
|
||||
return anotherParameter instanceof SqmNamedParameter<?>
|
||||
? one.getName().compareTo( ( (SqmNamedParameter<?>) anotherParameter ).getName() )
|
||||
? one.getName().compareTo( anotherParameter.getName() )
|
||||
: -1;
|
||||
}
|
||||
else if ( this instanceof SqmPositionalParameter ) {
|
||||
final SqmPositionalParameter<?> one = (SqmPositionalParameter<?>) this;
|
||||
return anotherParameter instanceof SqmPositionalParameter<?>
|
||||
? one.getPosition().compareTo( ( (SqmPositionalParameter<?>) anotherParameter ).getPosition() )
|
||||
? one.getPosition().compareTo( anotherParameter.getPosition() )
|
||||
: 1;
|
||||
}
|
||||
else if ( anotherParameter instanceof SqmJpaCriteriaParameterWrapper
|
||||
else if ( this instanceof SqmJpaCriteriaParameterWrapper
|
||||
&& anotherParameter instanceof SqmJpaCriteriaParameterWrapper ) {
|
||||
return Integer.compare( this.hashCode(), anotherParameter.hashCode() );
|
||||
}
|
||||
|
|
|
@ -86,7 +86,7 @@ public class SqmPositionalParameter<T> extends AbstractSqmParameter<T> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public int compare(SqmParameter anotherParameter) {
|
||||
public int compareTo(SqmParameter anotherParameter) {
|
||||
return anotherParameter instanceof SqmPositionalParameter<?>
|
||||
? getPosition().compareTo( ( (SqmPositionalParameter<?>) anotherParameter ).getPosition() )
|
||||
: 1;
|
||||
|
|
|
@ -6,8 +6,6 @@
|
|||
*/
|
||||
package org.hibernate.query.sqm.tree.expression;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import org.hibernate.query.BindableType;
|
||||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
|
@ -54,10 +52,7 @@ public class ValueBindJpaCriteriaParameter<T> extends JpaCriteriaParameter<T>{
|
|||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if ( this == o ) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return this == o;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -66,7 +61,7 @@ public class ValueBindJpaCriteriaParameter<T> extends JpaCriteriaParameter<T>{
|
|||
}
|
||||
|
||||
@Override
|
||||
public int compare(SqmParameter anotherParameter) {
|
||||
public int compareTo(SqmParameter anotherParameter) {
|
||||
if ( this == anotherParameter ) {
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -9,15 +9,23 @@ package org.hibernate.orm.test.jpa.criteria;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.dialect.DB2Dialect;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.dialect.H2Dialect;
|
||||
import org.hibernate.dialect.HSQLDialect;
|
||||
import org.hibernate.dialect.MariaDBDialect;
|
||||
import org.hibernate.dialect.MySQLDialect;
|
||||
import org.hibernate.dialect.SQLServerDialect;
|
||||
import org.hibernate.dialect.SybaseDialect;
|
||||
import org.hibernate.query.spi.QueryImplementor;
|
||||
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.hibernate.testing.orm.junit.DomainModel;
|
||||
import org.hibernate.testing.orm.junit.EntityManagerFactoryScope;
|
||||
import org.hibernate.testing.orm.junit.Jpa;
|
||||
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||
import org.hibernate.testing.orm.junit.SkipForDialect;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import jakarta.persistence.Entity;
|
||||
|
@ -30,42 +38,31 @@ import jakarta.persistence.criteria.Root;
|
|||
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
||||
@Jpa(annotatedClasses = {
|
||||
InPredicateTest.Event.class
|
||||
})
|
||||
/**
|
||||
* @implNote Skipped for Dialects which do not support at lease
|
||||
*/
|
||||
@TestForIssue(jiraKey = "HHH-15895")
|
||||
@DomainModel(annotatedClasses = InPredicateTest.Event.class)
|
||||
@SessionFactory(exportSchema = false)
|
||||
public class InPredicateTest {
|
||||
|
||||
@Test
|
||||
public void testInPredicate(EntityManagerFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
entityManager -> {
|
||||
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
|
||||
CriteriaQuery<Event> cr = cb.createQuery( Event.class );
|
||||
Root<Event> root = cr.from( Event.class );
|
||||
List<String> names = getNames( scope );
|
||||
cr.select( root ).where( root.get( "name" ).in( names ) );
|
||||
public void testInPredicate(SessionFactoryScope scope) {
|
||||
scope.inTransaction( (session) -> {
|
||||
CriteriaBuilder cb = session.getCriteriaBuilder();
|
||||
CriteriaQuery<Event> cr = cb.createQuery( Event.class );
|
||||
Root<Event> root = cr.from( Event.class );
|
||||
List<String> names = getNames();
|
||||
cr.select( root ).where( root.get( "name" ).in( names ) );
|
||||
|
||||
List<Event> results = entityManager.createQuery( cr ).getResultList();
|
||||
assertNotNull( results );
|
||||
}
|
||||
);
|
||||
// This should trigger the error from HHH-15895 as QuerySqmImpl
|
||||
// tries to handle the Criteria parameters
|
||||
session.createQuery( cr );
|
||||
} );
|
||||
}
|
||||
|
||||
private List<String> getNames(EntityManagerFactoryScope scope) {
|
||||
int maxNames;
|
||||
Dialect dialect = scope.getDialect();
|
||||
if ( dialect instanceof H2Dialect
|
||||
|| dialect instanceof MariaDBDialect
|
||||
|| dialect instanceof HSQLDialect
|
||||
|| dialect instanceof MySQLDialect ) {
|
||||
maxNames = 100000;
|
||||
}
|
||||
else {
|
||||
// the other dialects does not support 100000 parameters
|
||||
maxNames = 65500;
|
||||
}
|
||||
|
||||
private List<String> getNames() {
|
||||
int maxNames = 100000;
|
||||
List<String> names = new ArrayList<>( maxNames );
|
||||
for ( int i = 0; i < maxNames; i++ ) {
|
||||
names.add( "abc" + i );
|
||||
|
|
Loading…
Reference in New Issue