Fix binding issue for Criteria with paramters having the same name

This commit is contained in:
Andrea Boriero 2022-01-28 12:56:17 +01:00 committed by Andrea Boriero
parent 971d1ea2f4
commit fef147d6a4
3 changed files with 127 additions and 2 deletions

View File

@ -6,6 +6,8 @@
*/
package org.hibernate.query.sqm.tree.expression;
import java.util.Objects;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.procedure.spi.NamedCallableQueryMemento;
import org.hibernate.query.BindableType;
@ -160,4 +162,24 @@ public class JpaCriteriaParameter<T>
public void applySqlSelections(DomainResultCreationState creationState) {
throw new NotYetImplementedFor6Exception( getClass() );
}
@Override
public boolean equals(Object o) {
if ( this == o ) {
return true;
}
if ( o == null || getClass() != o.getClass() ) {
return false;
}
JpaCriteriaParameter<?> parameter = (JpaCriteriaParameter<?>) o;
return Objects.equals( name, parameter.name );
}
@Override
public int hashCode() {
if ( name == null ) {
return super.hashCode();
}
return Objects.hash( name );
}
}

View File

@ -49,4 +49,16 @@ public class ValueBindJpaCriteriaParameter<T> extends JpaCriteriaParameter<T>{
sb.append( value );
}
@Override
public boolean equals(Object o) {
if ( this == o ) {
return true;
}
return false;
}
@Override
public int hashCode() {
return System.identityHashCode( this );
}
}

View File

@ -10,6 +10,8 @@ import java.util.List;
import org.hibernate.testing.orm.junit.EntityManagerFactoryScope;
import org.hibernate.testing.orm.junit.Jpa;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import jakarta.persistence.Entity;
@ -18,8 +20,11 @@ import jakarta.persistence.Table;
import jakarta.persistence.TypedQuery;
import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.CriteriaQuery;
import jakarta.persistence.criteria.Predicate;
import jakarta.persistence.criteria.Root;
import static org.junit.jupiter.api.Assertions.assertEquals;
@Jpa(
annotatedClasses = {
CriteriaFunctionParametersBindingTest.Person.class
@ -27,11 +32,35 @@ import jakarta.persistence.criteria.Root;
)
public class CriteriaFunctionParametersBindingTest {
@BeforeEach
public void setUp(EntityManagerFactoryScope scope) {
scope.inTransaction(
entityManager -> {
Person person1 = new Person( 1, "Luigi" );
Person person2 = new Person( 2, null );
Person person3 = new Person( 3, "" );
Person person4 = new Person( 4, "Andrea" );
entityManager.persist( person1 );
entityManager.persist( person2 );
entityManager.persist( person3 );
entityManager.persist( person4 );
}
);
}
@AfterEach
public void tearDown(EntityManagerFactoryScope scope) {
scope.inTransaction( entityManager ->
entityManager.createQuery( "delete from Person" ).executeUpdate() );
}
@Test
public void testParameterBinding(EntityManagerFactoryScope scope) {
scope.inEntityManager(
entityManager -> {
final CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
@ -41,21 +70,68 @@ public class CriteriaFunctionParametersBindingTest {
person.get( "name" ),
criteriaBuilder.substring(
criteriaBuilder.parameter( String.class, "string" ),
criteriaBuilder.parameter( Integer.class, "start" )
criteriaBuilder.parameter( Integer.class, "start" ),
criteriaBuilder.parameter( Integer.class, "length" )
)
) );
criteriaQuery.select( person );
final TypedQuery<Person> query = entityManager.createQuery( criteriaQuery );
query.setParameter( "string", "andrea" );
query.setParameter( "string", "aLuigi" );
query.setParameter( "start", 2 );
query.setParameter( "length", 6 );
List<Person> people = query.getResultList();
assertEquals( 1, people.size() );
assertEquals( 1, people.get( 0 ).getId() );
}
);
}
@Test
public void testPredicateArray(EntityManagerFactoryScope scope) {
scope.inEntityManager(
entityManager -> {
final CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
final CriteriaQuery<String> query = criteriaBuilder.createQuery( String.class );
final Root<Person> person = query.from( Person.class );
final Predicate[] predicates = {
criteriaBuilder.equal(
person.get( "name" ),
criteriaBuilder.substring(
criteriaBuilder.parameter( String.class, "string" ),
criteriaBuilder.parameter( Integer.class, "start" ),
criteriaBuilder.parameter( Integer.class, "length" )
)
),
criteriaBuilder.equal(
person.get( "name" ),
criteriaBuilder.substring(
criteriaBuilder.parameter( String.class, "string" ),
criteriaBuilder.parameter( Integer.class, "start" ),
criteriaBuilder.parameter( Integer.class, "length" )
)
)
};
query.select( person.get( "name" ) ).having( predicates ).groupBy( person.get( "name" ) );
final TypedQuery<String> typedQuery = entityManager.createQuery( query );
typedQuery.setParameter( "string", "aLuigi" );
typedQuery.setParameter( "start", 2 );
typedQuery.setParameter( "length", 6 );
final List<String> names = typedQuery.getResultList();
assertEquals( 1, names.size() );
assertEquals( "Luigi", names.get( 0 ) );
}
);
}
@Entity(name = "Person")
@Table(name = "PERSON_TABLE")
public static class Person {
@ -65,6 +141,21 @@ public class CriteriaFunctionParametersBindingTest {
private String name;
public Person() {
}
public Person(Integer id, String name) {
this.id = id;
this.name = name;
}
public Integer getId() {
return id;
}
public String getName() {
return name;
}
}