HHH-13199 Add test case

This commit is contained in:
Guillaume Smet 2019-01-17 12:20:47 +01:00
parent e2510d9e3d
commit 9c72384e1f
1 changed files with 140 additions and 10 deletions

View File

@ -6,6 +6,14 @@
*/ */
package org.hibernate.jpa.test.criteria.simplecase; package org.hibernate.jpa.test.criteria.simplecase;
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import java.util.List;
import javax.persistence.AttributeConverter;
import javax.persistence.Convert;
import javax.persistence.Entity; import javax.persistence.Entity;
import javax.persistence.EntityManager; import javax.persistence.EntityManager;
import javax.persistence.GeneratedValue; import javax.persistence.GeneratedValue;
@ -13,22 +21,15 @@ import javax.persistence.Id;
import javax.persistence.Table; import javax.persistence.Table;
import javax.persistence.Tuple; import javax.persistence.Tuple;
import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaBuilder.SimpleCase;
import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Expression; import javax.persistence.criteria.Expression;
import javax.persistence.criteria.Path; import javax.persistence.criteria.Path;
import javax.persistence.criteria.Root; import javax.persistence.criteria.Root;
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
import org.junit.Test;
import org.hibernate.testing.TestForIssue; import org.hibernate.testing.TestForIssue;
import org.junit.Test;
import static javax.persistence.criteria.CriteriaBuilder.SimpleCase;
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
import static org.junit.Assert.assertEquals;
import java.util.List;
/** /**
* Mote that these are simply performing syntax checking (can the criteria query * Mote that these are simply performing syntax checking (can the criteria query
@ -40,7 +41,7 @@ public class BasicSimpleCaseTest extends BaseEntityManagerFunctionalTestCase {
@Override @Override
protected Class<?>[] getAnnotatedClasses() { protected Class<?>[] getAnnotatedClasses() {
return new Class[] {Customer.class}; return new Class[] {Customer.class, TestEntity.class};
} }
@Test @Test
@ -209,6 +210,67 @@ public class BasicSimpleCaseTest extends BaseEntityManagerFunctionalTestCase {
assertEquals( EmailType.UNKNOWN, results.get( 2 ).get( 1 ) ); assertEquals( EmailType.UNKNOWN, results.get( 2 ).get( 1 ) );
} }
@Test
@TestForIssue(jiraKey = "HHH-13199")
public void testCaseEnumInSum() throws Exception {
doInJPA( this::entityManagerFactory, em -> {
// create entities
TestEntity e1 = new TestEntity();
e1.setEnumField( TestEnum.VAL_1 );
e1.setValue( 20L );
em.persist( e1 );
TestEntity e2 = new TestEntity();
e2.setEnumField( TestEnum.VAL_2 );
e2.setValue( 10L );
em.persist( e2 );
} );
doInJPA( this::entityManagerFactory, em -> {
// Works in previous version (e.g. Hibernate 5.3.7.Final)
// Fails in Hibernate 5.4.0.Final
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Tuple> query = cb.createTupleQuery();
Root<TestEntity> r = query.from( TestEntity.class );
CriteriaBuilder.Case<Long> case1 = cb.selectCase();
case1.when( cb.equal( r.<TestEnum> get( "enumField" ), cb.literal( TestEnum.VAL_1 ) ),
r.<Long> get( "value" ) );
case1.otherwise( cb.nullLiteral( Long.class ) );
CriteriaBuilder.Case<Long> case2 = cb.selectCase();
case2.when( cb.equal( r.<TestEnum> get( "enumField" ), cb.literal( TestEnum.VAL_2 ) ),
r.<Long> get( "value" ) );
case2.otherwise( cb.nullLiteral( Long.class ) );
/*
* Forces enums to be bound as parameters, so SQL is something like
* "SELECT enumfield AS enumField, SUM(CASE WHEN enumfield = ? THEN value
* ELSE NULL END) AS VAL_1, SUM(CASE WHEN enumfield =? THEN value ELSE NULL END) AS VAL_1 FROM TestEntity
* GROUP BY enumfield"
*/
query
.select( cb.tuple( r.<TestEnum> get( "enumField" ).alias( "enumField" ),
cb.sum( case1 ).alias( "VAL_1" ),
cb.sum( case2 ).alias( "VAL_2" ) ) )
.groupBy( r.<TestEnum> get( "enumField" ) );
List<Tuple> list = em.createQuery( query ).getResultList();
assertEquals( 2, list.size() );
for ( Tuple tuple : list ) {
TestEnum enumVal = tuple.get( "enumField", TestEnum.class );
if ( enumVal == TestEnum.VAL_1 ) {
assertEquals( 20L, tuple.get( "VAL_1", Long.class ).longValue() );
assertNull( tuple.get( "VAL_2", Long.class ) );
}
else if ( enumVal == TestEnum.VAL_2 ) {
assertNull( tuple.get( "VAL_1", Long.class ) );
assertEquals( 10L, tuple.get( "VAL_2", Long.class ).longValue() );
}
}
} );
}
@Entity(name = "Customer") @Entity(name = "Customer")
@Table(name = "customer") @Table(name = "customer")
public static class Customer { public static class Customer {
@ -237,4 +299,72 @@ public class BasicSimpleCaseTest extends BaseEntityManagerFunctionalTestCase {
public enum EmailType { public enum EmailType {
LONG, NORMAL, UNKNOWN LONG, NORMAL, UNKNOWN
} }
@Entity(name = "TestEntity")
public static class TestEntity {
@Id
@GeneratedValue
private long id;
@Convert(converter = TestEnumConverter.class)
private TestEnum enumField;
private Long value;
public long getId() {
return id;
}
public TestEnum getEnumField() {
return enumField;
}
public void setEnumField(TestEnum enumField) {
this.enumField = enumField;
}
public Long getValue() {
return value;
}
public void setValue(Long value) {
this.value = value;
}
}
public static enum TestEnum {
VAL_1("1"),
VAL_2("2");
private final String value;
private TestEnum(String value) {
this.value = value;
}
public String getValue() {
return value;
}
public static TestEnum fromValue(String value) {
if (value.equals(VAL_1.value)) {
return VAL_1;
} else if (value.equals(VAL_2.value)) {
return VAL_2;
}
return null;
}
}
public static class TestEnumConverter implements AttributeConverter<TestEnum, String> {
@Override
public String convertToDatabaseColumn(TestEnum attribute) {
return attribute == null ? null : attribute.getValue();
}
@Override
public TestEnum convertToEntityAttribute(String dbData) {
return dbData == null ? null : TestEnum.fromValue(dbData);
}
}
} }