HHH-10502 - ORDER BY FIELD(..) throws java.sql.SQLException: Operand should contain 1 column(s)

This commit is contained in:
姜禹 2016-08-12 09:43:28 +08:00 committed by Vlad Mihalcea
parent 310139dbdc
commit 19834a0046
2 changed files with 110 additions and 1 deletions

View File

@ -182,10 +182,16 @@ public final class StringHelper {
// there is already a right-parenthesis; we assume there will be a matching right-parenthesis.
// 2) "... IN ?1", we assume that "?1" needs to be enclosed in parentheses, because there
// is no left-parenthesis.
// We need to check the placeholder is not used in `Order By FIELD(...)` (HHH-10502)
// Examples:
// " ... Order By FIELD(id,?1)", after expand parameters, the sql is "... Order By FIELD(id,?,?,?)"
boolean encloseInParens =
actuallyReplace
&& encloseInParensIfNecessary
&& !( getLastNonWhitespaceCharacter( beforePlaceholder ) == '(' );
&& !( getLastNonWhitespaceCharacter( beforePlaceholder ) == '(' ) &&
!( getLastNonWhitespaceCharacter( beforePlaceholder ) == ',' && getFirstNonWhitespaceCharacter(
afterPlaceholder ) == ')' );
StringBuilder buf = new StringBuilder( beforePlaceholder );
if ( encloseInParens ) {
buf.append( '(' );

View File

@ -0,0 +1,103 @@
/*
* 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.test.ordered;
import java.util.Arrays;
import java.util.List;
import javax.persistence.Entity;
import javax.persistence.Id;
import org.hibernate.dialect.MySQL5Dialect;
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
import org.hibernate.testing.RequiresDialect;
import org.hibernate.testing.TestForIssue;
import org.junit.Test;
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
import static org.junit.Assert.assertEquals;
/**
* @author Vlad Mihalcea
*/
public class HqlOrderByIdsTest extends BaseEntityManagerFunctionalTestCase {
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class<?>[] {
Person.class
};
}
@Test
@TestForIssue( jiraKey = "HHH-10502" )
@RequiresDialect( value = MySQL5Dialect.class )
public void testLifecycle() {
doInJPA( this::entityManagerFactory, entityManager -> {
Person person1 = new Person();
person1.setId( 1L );
person1.setName( "John" );
Person person2 = new Person();
person2.setId( 2L );
person2.setName( "Doe" );
Person person3 = new Person();
person3.setId( 3L );
person3.setName( "J" );
Person person4 = new Person();
person4.setId( 4L );
person4.setName( "D" );
entityManager.persist( person1 );
entityManager.persist( person2 );
entityManager.persist( person3 );
entityManager.persist( person4 );
} );
doInJPA( this::entityManagerFactory, entityManager -> {
List<Person> persons = entityManager.createQuery(
"SELECT p " +
"FROM Person p " +
"WHERE p.id IN (:ids) " +
"ORDER BY FIELD(id, :ids) ", Person.class)
.setParameter( "ids" , Arrays.asList(3L, 1L, 2L))
.getResultList();
assertEquals(3, persons.size());
int index = 0;
assertEquals( Long.valueOf( 3L ), persons.get( index++ ).getId() );
assertEquals( Long.valueOf( 1L ), persons.get( index++ ).getId() );
assertEquals( Long.valueOf( 2L ), persons.get( index++ ).getId() );
} );
}
@Entity(name = "Person")
public static class Person {
@Id
private Long id;
private String name;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
}