diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/metamodel/generics/embeddable/AbstractValueObject.java b/hibernate-core/src/test/java/org/hibernate/orm/test/metamodel/generics/embeddable/AbstractValueObject.java new file mode 100644 index 0000000000..3b9e409809 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/metamodel/generics/embeddable/AbstractValueObject.java @@ -0,0 +1,34 @@ +/* + * 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.orm.test.metamodel.generics.embeddable; + +import java.io.Serializable; + +import jakarta.persistence.Column; +import jakarta.persistence.MappedSuperclass; + +@MappedSuperclass +public abstract class AbstractValueObject> implements Serializable, + Comparable> { + public static final String VALUE = "value"; + + @Column( name = "value_col" ) + private V value; + + protected AbstractValueObject() { + super(); + } + + protected AbstractValueObject(final V value) { + this.value = value; + } + + @Override + public int compareTo(final AbstractValueObject object) { + return value.compareTo( object.value ); + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/metamodel/generics/embeddable/CreationDate.java b/hibernate-core/src/test/java/org/hibernate/orm/test/metamodel/generics/embeddable/CreationDate.java new file mode 100644 index 0000000000..21700a1cb1 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/metamodel/generics/embeddable/CreationDate.java @@ -0,0 +1,22 @@ +/* + * 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.orm.test.metamodel.generics.embeddable; + +import java.util.Date; + +import jakarta.persistence.Embeddable; + +@Embeddable +public class CreationDate extends AbstractValueObject { + protected CreationDate() { + super(); + } + + public CreationDate(final Date value) { + super( value ); + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/metamodel/generics/embeddable/GenericEmbeddableSuperclassMetamodelTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/metamodel/generics/embeddable/GenericEmbeddableSuperclassMetamodelTest.java new file mode 100644 index 0000000000..474085add4 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/metamodel/generics/embeddable/GenericEmbeddableSuperclassMetamodelTest.java @@ -0,0 +1,80 @@ +/* + * 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.orm.test.metamodel.generics.embeddable; + +import java.util.Date; + +import org.hibernate.SessionFactory; + +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.Tuple; +import jakarta.persistence.TypedQuery; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Expression; +import jakarta.persistence.criteria.Path; +import jakarta.persistence.criteria.Root; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * @author Marco Belladelli + */ +@Jpa( annotatedClasses = { + Parent.class, + AbstractValueObject.class, + CreationDate.class, + SomeNumber.class, + SomeString.class, +} ) +@Jira( "https://hibernate.atlassian.net/browse/HHH-18490" ) +public class GenericEmbeddableSuperclassMetamodelTest { + @SuppressWarnings( { "rawtypes", "unchecked" } ) + @Test + public void test(EntityManagerFactoryScope scope) { + scope.inTransaction( entityManager -> { + final CriteriaBuilder cb = entityManager.getCriteriaBuilder(); + final CriteriaQuery cq = cb.createTupleQuery(); + final Root from = cq.from( Parent.class ); + + final Path someStringPath = from.get( Parent_.someString ).get( SomeString_.value ); + final Path someNumberPath = from.get( Parent_.someNumber ).get( SomeNumber_.value ); + final Path timestampPath = from.get( Parent_.date ).get( CreationDate_.value ); + final Expression maxNumber = cb.max( someNumberPath ); + final Expression maxTimestamp = cb.function( "max", Date.class, timestampPath ); + cq.select( cb.tuple( someStringPath, maxTimestamp, maxNumber ) ); + cq.groupBy( someStringPath ); + + final TypedQuery query = entityManager.createQuery( cq ); + final Tuple result = query.getSingleResult(); + + assertThat( result.get( 0, String.class ) ).isEqualTo( "something" ); + assertThat( result.get( 1, Date.class ) ).isNotNull(); + assertThat( result.get( 2, Object.class ) ).isEqualTo( 42 ); + } ); + } + + @BeforeAll + public void setUp(EntityManagerFactoryScope scope) { + scope.inTransaction( entityManager -> entityManager.persist( new Parent( + new SomeString( "something" ), + new CreationDate( new Date() ), + new SomeNumber( 42 ) + ) ) ); + } + + @AfterAll + public void tearDown(EntityManagerFactoryScope scope) { + scope.getEntityManagerFactory().unwrap( SessionFactory.class ).getSchemaManager().truncateMappedObjects(); + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/metamodel/generics/embeddable/Parent.java b/hibernate-core/src/test/java/org/hibernate/orm/test/metamodel/generics/embeddable/Parent.java new file mode 100644 index 0000000000..17898c5b48 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/metamodel/generics/embeddable/Parent.java @@ -0,0 +1,44 @@ +/* + * 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.orm.test.metamodel.generics.embeddable; + +import jakarta.persistence.AttributeOverride; +import jakarta.persistence.Column; +import jakarta.persistence.Embedded; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; + +import static org.hibernate.orm.test.metamodel.generics.embeddable.AbstractValueObject.VALUE; + +@Entity +public class Parent { + @Id + @GeneratedValue + private Long id; + + @Embedded + @AttributeOverride( name = VALUE, column = @Column( name = "some_string" ) ) + private SomeString someString; + + @Embedded + @AttributeOverride( name = VALUE, column = @Column( name = "some_date" ) ) + private CreationDate date; + + @Embedded + @AttributeOverride( name = VALUE, column = @Column( name = "some_number" ) ) + private SomeNumber someNumber; + + public Parent() { + } + + public Parent(final SomeString someString, final CreationDate date, final SomeNumber someNumber) { + this.someString = someString; + this.date = date; + this.someNumber = someNumber; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/metamodel/generics/embeddable/SomeNumber.java b/hibernate-core/src/test/java/org/hibernate/orm/test/metamodel/generics/embeddable/SomeNumber.java new file mode 100644 index 0000000000..3f618556ed --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/metamodel/generics/embeddable/SomeNumber.java @@ -0,0 +1,19 @@ +/* + * 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.orm.test.metamodel.generics.embeddable; + +import jakarta.persistence.Embeddable; + +@Embeddable +public class SomeNumber extends AbstractValueObject { + protected SomeNumber() { + } + + public SomeNumber(final Integer value) { + super( value ); + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/metamodel/generics/embeddable/SomeString.java b/hibernate-core/src/test/java/org/hibernate/orm/test/metamodel/generics/embeddable/SomeString.java new file mode 100644 index 0000000000..825a743d38 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/metamodel/generics/embeddable/SomeString.java @@ -0,0 +1,13 @@ +package org.hibernate.orm.test.metamodel.generics.embeddable; + +import jakarta.persistence.Embeddable; + +@Embeddable +public class SomeString extends AbstractValueObject { + protected SomeString() { + } + + public SomeString(final String value) { + super( value ); + } +}