From 33efabd5976c8e02faf9366679ac4424eeb82897 Mon Sep 17 00:00:00 2001 From: Vlad Mihalcea Date: Wed, 19 Dec 2018 11:27:41 +0200 Subject: [PATCH] HHH-13167 - When omitting the OTHERWISE clause in a CASE expression built with Criteria API, Hibernate throws a NullPointerException --- .../expression/SearchedCaseExpression.java | 11 ++-- .../SearchedCaseExpressionTest.java | 51 ++++++++++++++++--- 2 files changed, 52 insertions(+), 10 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/query/criteria/internal/expression/SearchedCaseExpression.java b/hibernate-core/src/main/java/org/hibernate/query/criteria/internal/expression/SearchedCaseExpression.java index f3e2357deb..8caab31ec3 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/criteria/internal/expression/SearchedCaseExpression.java +++ b/hibernate-core/src/main/java/org/hibernate/query/criteria/internal/expression/SearchedCaseExpression.java @@ -114,9 +114,14 @@ public class SearchedCaseExpression .append( ( (Renderable) whenClause.getResult() ).render( renderingContext ) ); } - caseStatement.append( " else " ) - .append( ( (Renderable) getOtherwiseResult() ).render( renderingContext ) ) - .append( " end" ); + Expression otherwiseResult = getOtherwiseResult(); + + if ( otherwiseResult != null ) { + caseStatement.append( " else " ) + .append( ( (Renderable) otherwiseResult ).render( renderingContext ) ); + } + + caseStatement.append( " end" ); return caseStatement.toString(); } diff --git a/hibernate-core/src/test/java/org/hibernate/query/criteria/internal/expression/SearchedCaseExpressionTest.java b/hibernate-core/src/test/java/org/hibernate/query/criteria/internal/expression/SearchedCaseExpressionTest.java index 228df1c517..c92d60c619 100644 --- a/hibernate-core/src/test/java/org/hibernate/query/criteria/internal/expression/SearchedCaseExpressionTest.java +++ b/hibernate-core/src/test/java/org/hibernate/query/criteria/internal/expression/SearchedCaseExpressionTest.java @@ -24,11 +24,13 @@ import org.hibernate.dialect.PostgreSQL81Dialect; import org.hibernate.testing.RequiresDialect; import org.hibernate.testing.SkipForDialect; +import org.hibernate.testing.TestForIssue; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import org.junit.Assert; import org.junit.Test; import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate; +import static org.junit.Assert.assertEquals; /** * @@ -83,14 +85,49 @@ public class SearchedCaseExpressionTest extends BaseCoreFunctionalTestCase { Assert.assertNotNull(resultList); } ); - } + } - @Override - protected Class[] getAnnotatedClasses() { - return new Class[]{Event.class, EventType.class}; - } + @Test + @TestForIssue(jiraKey = "HHH-13167") + public void testMissingElseClause() { + doInHibernate( this::sessionFactory, session -> { + Event event = new Event(); + event.id = 1L; + event.type = EventType.TYPE1; - @Entity(name = "Event") + session.persist( event ); + } ); + + doInHibernate( this::sessionFactory, session -> { + CriteriaBuilder cb = session.getCriteriaBuilder(); + + CriteriaQuery criteria = cb.createQuery( Event.class ); + + Root root = criteria.from( Event.class ); + Path type = root.get( "type" ); + + Expression caseWhen = cb. selectCase() + .when( cb.equal( type, EventType.TYPE1 ), "Matched" ); + + criteria.select( root ); + criteria.where( cb.equal( caseWhen, "Matched" ) ); + + Event event = session.createQuery( criteria ).getSingleResult(); + assertEquals( 1L, (long) event.id ); + } ); + } + + @Override + protected boolean isCleanupTestDataRequired() { + return true; + } + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[]{ Event.class, EventType.class }; + } + + @Entity(name = "Event") public static class Event { @Id @@ -113,7 +150,7 @@ public class SearchedCaseExpressionTest extends BaseCoreFunctionalTestCase { } } - public enum EventType { + public enum EventType { TYPE1, TYPE2, TYPE3