diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/criteria/CoalesceTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/criteria/CoalesceTest.java index 33c18bb7e4..423738afd7 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/criteria/CoalesceTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/criteria/CoalesceTest.java @@ -4,15 +4,24 @@ */ package org.hibernate.orm.test.jpa.criteria; +import java.math.BigDecimal; +import java.util.List; + import org.hibernate.testing.orm.junit.JiraKey; import org.hibernate.testing.orm.junit.EntityManagerFactoryScope; +import org.hibernate.testing.orm.junit.Jira; import org.hibernate.testing.orm.junit.Jpa; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import jakarta.persistence.Column; +import jakarta.persistence.Embeddable; +import jakarta.persistence.Embedded; import jakarta.persistence.Entity; import jakarta.persistence.Id; +import jakarta.persistence.Tuple; import jakarta.persistence.TypedQuery; import jakarta.persistence.criteria.CriteriaBuilder; import jakarta.persistence.criteria.CriteriaQuery; @@ -20,13 +29,18 @@ import jakarta.persistence.criteria.Expression; import jakarta.persistence.criteria.ParameterExpression; import jakarta.persistence.criteria.Root; +import static org.assertj.core.api.Assertions.assertThat; + /** * @author Will Dazy */ -@Jpa(annotatedClasses = CoalesceTest.HHH15291Entity.class) +@Jpa( annotatedClasses = { + CoalesceTest.HHH15291Entity.class, + CoalesceTest.ComponentEntity.class, + CoalesceTest.ComponentA.class, +} ) @JiraKey( value = "HHH-15291") public class CoalesceTest { - @Test public void hhh15291JPQL1Test(EntityManagerFactoryScope scope) { scope.inEntityManager( @@ -95,9 +109,74 @@ public class CoalesceTest { ); } + @Test + @Jira( "https://hibernate.atlassian.net/browse/HHH-18321" ) + public void testCoalesceInBinaryArithmetic(EntityManagerFactoryScope scope) { + scope.inTransaction( entityManager -> { + final CriteriaBuilder cb = entityManager.getCriteriaBuilder(); + final CriteriaQuery cquery = cb.createTupleQuery(); + final Root root = cquery.from( ComponentEntity.class ); + + cquery.select( cb.tuple( + root.get( "id" ), + cb.diff( + cb.coalesce( root.get( "componentA" ).get( "income" ), BigDecimal.ZERO ), + cb.coalesce( root.get( "componentA" ).get( "expense" ), BigDecimal.ZERO ) + ) + ) ); + + final List resultList = entityManager.createQuery( cquery ).getResultList(); + assertThat( resultList ).hasSize( 2 ); + for ( Tuple result : resultList ) { + final Long id = result.get( 0, Long.class ); + assertThat( result.get( 1, BigDecimal.class ).intValue() ).isEqualTo( id == 1L ? 0 : 1 ); + } + } ); + } + + @Test + @Jira( "https://hibernate.atlassian.net/browse/HHH-18321" ) + public void testCoalesceInBinaryArithmeticParam(EntityManagerFactoryScope scope) { + scope.inTransaction( entityManager -> { + final CriteriaBuilder cb = entityManager.getCriteriaBuilder(); + final CriteriaQuery cquery = cb.createTupleQuery(); + final Root root = cquery.from( ComponentEntity.class ); + + final ParameterExpression defaultValue = cb.parameter( BigDecimal.class, "default-value" ); + + cquery.select( cb.tuple( + root.get( "id" ), + cb.diff( + defaultValue, + cb.coalesce( root.get( "componentA" ).get( "expense" ), defaultValue ) + ) + ) ); + + final List resultList = entityManager.createQuery( cquery ) + .setParameter( "default-value", BigDecimal.ZERO ).getResultList(); + assertThat( resultList ).hasSize( 2 ); + for ( Tuple result : resultList ) { + final Long id = result.get( 0, Long.class ); + assertThat( result.get( 1, BigDecimal.class ).intValue() ).isEqualTo( id == 1L ? -1 : 0 ); + } + } ); + } + + @BeforeAll + public void setUp(EntityManagerFactoryScope scope) { + scope.inTransaction( entityManager -> { + entityManager.persist( new ComponentEntity( 1L, new ComponentA( BigDecimal.ONE, BigDecimal.ONE ) ) ); + entityManager.persist( new ComponentEntity( 2L, new ComponentA( BigDecimal.ONE, null ) ) ); + } ); + } + + @AfterAll + public void tearDown(EntityManagerFactoryScope scope) { + scope.inTransaction( entityManager -> entityManager.createQuery( "delete from ComponentEntity" ).executeUpdate() ); + } + @Entity(name = "HHH15291Entity") public static class HHH15291Entity { - @Id @Column(name = "KEY_CHAR") private String KeyString; @@ -116,53 +195,36 @@ public class CoalesceTest { @Column(name = "ITEM_INTEGER1") private Integer itemInteger1; + } - public String getKeyString() { - return KeyString; + @Entity( name = "ComponentEntity" ) + static class ComponentEntity { + @Id + private Long id; + + @Embedded + private ComponentA componentA; + + public ComponentEntity() { } - public void setKeyString(String keyString) { - KeyString = keyString; + public ComponentEntity(Long id, ComponentA componentA) { + this.id = id; + this.componentA = componentA; + } + } + + @Embeddable + static class ComponentA { + private BigDecimal income; + private BigDecimal expense; + + public ComponentA() { } - public String getItemString1() { - return itemString1; - } - - public void setItemString1(String itemString1) { - this.itemString1 = itemString1; - } - - public String getItemString2() { - return itemString2; - } - - public void setItemString2(String itemString2) { - this.itemString2 = itemString2; - } - - public String getItemString3() { - return itemString3; - } - - public void setItemString3(String itemString3) { - this.itemString3 = itemString3; - } - - public String getItemString4() { - return itemString4; - } - - public void setItemString4(String itemString4) { - this.itemString4 = itemString4; - } - - public Integer getItemInteger1() { - return itemInteger1; - } - - public void setItemInteger1(Integer itemInteger1) { - this.itemInteger1 = itemInteger1; + public ComponentA(BigDecimal income, BigDecimal expense) { + this.income = income; + this.expense = expense; } } }