Potential bug in SearchedCaseExpression type handling

Description

While debugging some more sophisticated case-when-then expression compilations, I stumpled upon a potential flaw in org.hibernate.jpa.criteria.expression.SearchedCaseExpression#javaType, which possible was introduced to lazily assign the expression's type based on either -case-when result's type or a case-otherwise type.

Actually org.hibernate.jpa.criteria.expression.SearchedCaseExpression#javaType does get written, but never gets read, so it's more or less dead code. If one requests SearchedCaseExpression's type, null will be returned, as the method is implemented in org.hibernate.jpa.criteria.expression.AbstractTupleElement (which still references javaType as null) and not overriden in SearchedCaseExpression.

I am sure, this was not intended and may lead to bugs. A possible fix would look like either SearchedCaseExpression needs to override getJavaType() or SearchedCaseExpression#adjustJavaType(Expression) needs to delegates the expression's type via AbstractTupleElement#resetJavaType(Class) to it's orignal field.

wdyt?

Attachments

1
  • 25 Jun 2015, 09:59 AM

Activity

Show:

Andrea Boriero September 4, 2015 at 1:38 PM

Andrea Boriero September 2, 2015 at 2:35 PM

Andrea Boriero June 25, 2015 at 9:51 AM

hi thanks for the test, may be this can help you with eclipse https://developer.jboss.org/wiki/ContributingToHibernateUsingEclipse

Sven Linstaedt June 15, 2015 at 1:28 PM

Sorry for not supplying a pull request, but I was not able to figure out how to get a working hibernate workspace up and running using Eclipse under Windows.

Interestingly the work around with down casting the value type as mentioned in https://hibernate.atlassian.net/browse/HHH-4700#icft=HHH-4700 and https://hibernate.atlassian.net/browse/HHH-9343#icft=HHH-9343 is not working anymore on the current 4.3.x branch. At least on 4.1.4 it was working.

package test; public class SelectCaseTest { @javax.persistence.Entity public static class Entity { @Id private Long id; @Enumerated(EnumType.STRING) private EnumValue value; } public enum EnumValue { VALUE_1, VALUE_2; } private static EntityManagerFactory factory; private EntityManager entityManager; @BeforeClass public static void beforeClass() { factory = Persistence.createEntityManagerFactory("test"); } @AfterClass public static void afterClass() { factory.close(); } @Before public void before() { entityManager = factory.createEntityManager(); } @After public void after() { entityManager.close(); } @Test public void selectCaseWithValuesShouldWork() { CriteriaBuilder cb = entityManager.getCriteriaBuilder(); Case<EnumValue> selectCase = cb.selectCase(); Predicate somePredicate = cb.equal(cb.literal(1), 1); selectCase.when(somePredicate, EnumValue.VALUE_1); selectCase.otherwise(EnumValue.VALUE_2); CriteriaQuery<Entity> query = cb.createQuery(Entity.class); Root<Entity> from = query.from(Entity.class); query.select(from).where(cb.equal(from.get("value"), selectCase)); List<?> result = entityManager.createQuery(query).getResultList(); System.out.println(result); } @Test public void selectCaseWithCastedTypeValuesShouldWork() { CriteriaBuilder cb = entityManager.getCriteriaBuilder(); Case<String> selectCase = cb.selectCase(); Predicate somePredicate = cb.equal(cb.literal(1), 1); selectCase.when(somePredicate, EnumValue.VALUE_1.name()); selectCase.otherwise(EnumValue.VALUE_2.name()); CriteriaQuery<Entity> query = cb.createQuery(Entity.class); Root<Entity> from = query.from(Entity.class); query.select(from).where(cb.equal(from.get("value"), selectCase.as(String.class))); List<?> result = entityManager.createQuery(query).getResultList(); System.out.println(result); } @Test public void simpleSelectCaseWithValuesShouldWork() { CriteriaBuilder cb = entityManager.getCriteriaBuilder(); SimpleCase<Integer, EnumValue> selectCase = cb.selectCase(cb.literal(1)); selectCase.when(1, EnumValue.VALUE_1); selectCase.otherwise(EnumValue.VALUE_2); CriteriaQuery<Entity> query = cb.createQuery(Entity.class); Root<Entity> from = query.from(Entity.class); query.select(from).where(cb.equal(from.get("value"), selectCase)); List<?> result = entityManager.createQuery(query).getResultList(); System.out.println(result); } @Test public void simpleSelectCaseWithCastedTypeValuesShouldWork() { CriteriaBuilder cb = entityManager.getCriteriaBuilder(); SimpleCase<Integer, String> selectCase = cb.selectCase(cb.literal(1)); selectCase.when(1, EnumValue.VALUE_1.name()); selectCase.otherwise(EnumValue.VALUE_2.name()); CriteriaQuery<Entity> query = cb.createQuery(Entity.class); Root<Entity> from = query.from(Entity.class); query.select(from).where(cb.equal(from.get("value"), selectCase.as(String.class))); List<?> result = entityManager.createQuery(query).getResultList(); System.out.println(result); } }
<?xml version="1.0" encoding="UTF-8"?> <persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"> <persistence-unit name="test" transaction-type="RESOURCE_LOCAL"> <class>test.SelectCaseTest$Entity</class> <properties> <property name="javax.persistence.jdbc.driver" value="org.hsqldb.jdbcDriver" /> <property name="javax.persistence.jdbc.url" value="jdbc:hsqldb:file:target/testdb;shutdown=true" /> <property name="javax.persistence.jdbc.user" value="sa" /> <property name="javax.persistence.jdbc.password" value="" /> <property name="hibernate.hbm2ddl.auto" value="update" /> <property name="hibernate.archive.autodetection" value="class" /> <property name="hibernate.flushMode" value="FLUSH_AUTO" /> <property name="hibernate.hbm2ddl.auto" value="create" /> <property name="hibernate.show_sql" value="true"/> </properties> </persistence-unit> </persistence>

Andrea Boriero June 9, 2015 at 9:21 AM

Hi can you provide the test case,
thanks

Fixed

Details

Assignee

Reporter

Fix versions

Affects versions

Priority

Created April 17, 2015 at 12:02 PM
Updated September 30, 2015 at 6:35 PM
Resolved September 4, 2015 at 1:38 PM