From b9351cffc6ee2f8b1fb838b46ce9a0e714d0352b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=8Cedomir=20Igaly?= Date: Fri, 8 Nov 2024 13:59:16 +0100 Subject: [PATCH] HHH-18829 Test: - Hibernate Processor - generate ID class in metadata class if entity not annotated with @IdClass; order of record components must match order of properties in entity class - Hibernate Core - check if ID class has been properly generated with preserved order of components - Annotated existing test entity classes with @Exclude when ID class can not be generated without causing compilation errors --- .../bidirectional/Order.java | 2 + .../bidirectional/OrderLine.java | 2 + .../bidirectional/Product.java | 2 + .../hhh18829/AutoGeneratedIdClassTest.java | 52 ++++++++++++++++++ .../hhh18829/EmployeeWithoutIdClass.java | 17 ++++++ .../processor/test/hhh18829/Address.java | 12 +++++ .../test/hhh18829/AnotherEmployee.java | 33 ++++++++++++ .../hhh18829/AutoGeneratedIdClassTest.java | 53 +++++++++++++++++++ .../processor/test/hhh18829/Employee.java | 17 ++++++ .../test/hhh18829/EmployeeWithIdClass.java | 22 ++++++++ 10 files changed, 212 insertions(+) create mode 100644 hibernate-core/src/test/java/org/hibernate/orm/test/mapping/hhh18829/AutoGeneratedIdClassTest.java create mode 100644 hibernate-core/src/test/java/org/hibernate/orm/test/mapping/hhh18829/EmployeeWithoutIdClass.java create mode 100644 tooling/metamodel-generator/src/test/java/org/hibernate/processor/test/hhh18829/Address.java create mode 100644 tooling/metamodel-generator/src/test/java/org/hibernate/processor/test/hhh18829/AnotherEmployee.java create mode 100644 tooling/metamodel-generator/src/test/java/org/hibernate/processor/test/hhh18829/AutoGeneratedIdClassTest.java create mode 100644 tooling/metamodel-generator/src/test/java/org/hibernate/processor/test/hhh18829/Employee.java create mode 100644 tooling/metamodel-generator/src/test/java/org/hibernate/processor/test/hhh18829/EmployeeWithIdClass.java diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/derivedidentities/bidirectional/Order.java b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/derivedidentities/bidirectional/Order.java index cc624bb9e5..470f5983b5 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/derivedidentities/bidirectional/Order.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/derivedidentities/bidirectional/Order.java @@ -13,9 +13,11 @@ import jakarta.persistence.GeneratedValue; import jakarta.persistence.Id; import jakarta.persistence.OneToMany; import jakarta.persistence.Table; +import org.hibernate.annotations.processing.Exclude; @SuppressWarnings("serial") @Entity +@Exclude @Table(name = "orders") public class Order implements Serializable { diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/derivedidentities/bidirectional/OrderLine.java b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/derivedidentities/bidirectional/OrderLine.java index 2eed3be99c..97bba26f34 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/derivedidentities/bidirectional/OrderLine.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/derivedidentities/bidirectional/OrderLine.java @@ -10,9 +10,11 @@ import jakarta.persistence.Id; import jakarta.persistence.JoinColumn; import jakarta.persistence.ManyToOne; import jakarta.persistence.Table; +import org.hibernate.annotations.processing.Exclude; @SuppressWarnings("serial") @Entity +@Exclude @Table(name = "order_line") // @IdClass(OrderLinePK.class) public class OrderLine implements Serializable diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/derivedidentities/bidirectional/Product.java b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/derivedidentities/bidirectional/Product.java index dce2a99c93..69fc69c138 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/derivedidentities/bidirectional/Product.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/annotations/derivedidentities/bidirectional/Product.java @@ -9,9 +9,11 @@ import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; import jakarta.persistence.Id; import jakarta.persistence.Table; +import org.hibernate.annotations.processing.Exclude; @SuppressWarnings("serial") @Entity +@Exclude @Table(name = "products") public class Product implements Serializable { diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/hhh18829/AutoGeneratedIdClassTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/hhh18829/AutoGeneratedIdClassTest.java new file mode 100644 index 0000000000..ef51add96b --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/hhh18829/AutoGeneratedIdClassTest.java @@ -0,0 +1,52 @@ +/* + * SPDX-License-Identifier: LGPL-2.1-or-later + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.orm.test.mapping.hhh18829; + +import org.hibernate.testing.orm.junit.DomainModel; +import org.hibernate.testing.orm.junit.JiraKey; +import org.hibernate.testing.orm.junit.SessionFactory; +import org.hibernate.testing.orm.junit.SessionFactoryScope; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import java.lang.reflect.InvocationTargetException; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +@DomainModel(annotatedClasses = EmployeeWithoutIdClass.class) +@JiraKey(" HHH-18829") +@SessionFactory +public class AutoGeneratedIdClassTest { + + @BeforeAll + void setUp(SessionFactoryScope sessionFactoryScope) { + sessionFactoryScope.inTransaction( sess -> { + final var one = new EmployeeWithoutIdClass(); + one.empName = "John Doe"; + one.empId = 1; + one.address = "10 Downing Street, SW1A 2AA"; + sess.persist( one ); + + final var two = new EmployeeWithoutIdClass(); + two.empName = "Dave Default"; + two.empId = 1; + two.address = "1600 Pennsylvania Avenue"; + sess.persist( two ); + } ); + } + + @Test + public void test(SessionFactoryScope sessionFactoryScope) + throws ClassNotFoundException, InvocationTargetException, InstantiationException, IllegalAccessException { + final var idClass = Class.forName( EmployeeWithoutIdClass.class.getName() + "_$Id" ); + final var id = idClass.getConstructors()[0].newInstance( "John Doe", 1 ); + final var employees = sessionFactoryScope.fromSession( + sess -> sess.createQuery( "from EmployeeWithoutIdClass where id=:id", EmployeeWithoutIdClass.class ).setParameter( "id", id ) + .getResultList() + ); + assertEquals( 1, employees.size() ); + assertEquals( "10 Downing Street, SW1A 2AA", employees.get( 0 ).address ); + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/hhh18829/EmployeeWithoutIdClass.java b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/hhh18829/EmployeeWithoutIdClass.java new file mode 100644 index 0000000000..9ea1b8d14b --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/hhh18829/EmployeeWithoutIdClass.java @@ -0,0 +1,17 @@ +/* + * SPDX-License-Identifier: LGPL-2.1-or-later + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.orm.test.mapping.hhh18829; + +import jakarta.persistence.Entity; +import jakarta.persistence.Id; + +@Entity +public class EmployeeWithoutIdClass { + @Id + String empName; + @Id + Integer empId; + String address; +} diff --git a/tooling/metamodel-generator/src/test/java/org/hibernate/processor/test/hhh18829/Address.java b/tooling/metamodel-generator/src/test/java/org/hibernate/processor/test/hhh18829/Address.java new file mode 100644 index 0000000000..e07d21e87d --- /dev/null +++ b/tooling/metamodel-generator/src/test/java/org/hibernate/processor/test/hhh18829/Address.java @@ -0,0 +1,12 @@ +/* + * SPDX-License-Identifier: LGPL-2.1-or-later + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.processor.test.hhh18829; + +import jakarta.persistence.MappedSuperclass; + +@MappedSuperclass +public class Address { + String address; +} diff --git a/tooling/metamodel-generator/src/test/java/org/hibernate/processor/test/hhh18829/AnotherEmployee.java b/tooling/metamodel-generator/src/test/java/org/hibernate/processor/test/hhh18829/AnotherEmployee.java new file mode 100644 index 0000000000..5cc782856f --- /dev/null +++ b/tooling/metamodel-generator/src/test/java/org/hibernate/processor/test/hhh18829/AnotherEmployee.java @@ -0,0 +1,33 @@ +/* + * SPDX-License-Identifier: LGPL-2.1-or-later + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.processor.test.hhh18829; + +import jakarta.persistence.Entity; +import jakarta.persistence.Id; + +@Entity +public class AnotherEmployee extends Address { + Integer empId; + + String empName; + + @Id + public Integer getEmpId() { + return empId; + } + + public void setEmpId(Integer empId) { + this.empId = empId; + } + + @Id + public String getEmpName() { + return empName; + } + + public void setEmpName(String empName) { + this.empName = empName; + } +} diff --git a/tooling/metamodel-generator/src/test/java/org/hibernate/processor/test/hhh18829/AutoGeneratedIdClassTest.java b/tooling/metamodel-generator/src/test/java/org/hibernate/processor/test/hhh18829/AutoGeneratedIdClassTest.java new file mode 100644 index 0000000000..58e73bf333 --- /dev/null +++ b/tooling/metamodel-generator/src/test/java/org/hibernate/processor/test/hhh18829/AutoGeneratedIdClassTest.java @@ -0,0 +1,53 @@ +/* + * SPDX-License-Identifier: LGPL-2.1-or-later + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.processor.test.hhh18829; + +import org.hibernate.processor.test.util.CompilationTest; +import org.hibernate.processor.test.util.TestForIssue; +import org.hibernate.processor.test.util.TestUtil; +import org.hibernate.processor.test.util.WithClasses; +import org.junit.Test; + +import java.lang.reflect.RecordComponent; +import java.util.Arrays; + +import static org.hibernate.processor.test.util.TestUtil.getMetamodelClassFor; +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +@TestForIssue(jiraKey = " HHH-18829") +public class AutoGeneratedIdClassTest extends CompilationTest { + + @Test + @WithClasses({Employee.class, AnotherEmployee.class, Address.class, EmployeeWithIdClass.class}) + @TestForIssue(jiraKey = "HHH-18829") + public void test() { + System.out.println( TestUtil.getMetaModelSourceAsString( Employee.class ) ); + System.out.println( TestUtil.getMetaModelSourceAsString( AnotherEmployee.class ) ); + System.out.println( TestUtil.getMetaModelSourceAsString( Address.class ) ); + System.out.println( TestUtil.getMetaModelSourceAsString( EmployeeWithIdClass.class ) ); + + checkIfIdClassIsGenerated( Employee.class, new String[] {"empName", "empId"} ); + checkIfIdClassIsGenerated( AnotherEmployee.class, new String[] {"empId", "empName"} ); + + final var clazz = getMetamodelClassFor( EmployeeWithIdClass.class ); + assertTrue( Arrays.stream( clazz.getClasses() ).map( Class::getSimpleName ) + .noneMatch( "Id"::equals ), + "EmployeeWithIdClass_ should not have inner class Id" ); + } + + private static void checkIfIdClassIsGenerated(Class entityClass, String[] idComponentNames) { + final var clazz = getMetamodelClassFor( entityClass ); + final var maybeIdClass = Arrays.stream( clazz.getClasses() ) + .filter( c -> c.getSimpleName().equals( "Id" ) ).findAny(); + assertTrue( maybeIdClass.isPresent(), () -> clazz.getSimpleName() + "_ should have inner class Id" ); + final Class idClass = maybeIdClass.get(); + assertTrue( idClass.isRecord(), "Generated ID class should be a record" ); + assertArrayEquals( + idComponentNames, + Arrays.stream( idClass.getRecordComponents() ).map( RecordComponent::getName ).toArray( String[]::new ) + ); + } +} diff --git a/tooling/metamodel-generator/src/test/java/org/hibernate/processor/test/hhh18829/Employee.java b/tooling/metamodel-generator/src/test/java/org/hibernate/processor/test/hhh18829/Employee.java new file mode 100644 index 0000000000..4ef9535d39 --- /dev/null +++ b/tooling/metamodel-generator/src/test/java/org/hibernate/processor/test/hhh18829/Employee.java @@ -0,0 +1,17 @@ +/* + * SPDX-License-Identifier: LGPL-2.1-or-later + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.processor.test.hhh18829; + +import jakarta.persistence.Entity; +import jakarta.persistence.Id; + +@Entity +public class Employee extends Address { + @Id + String empName; + @Id + Integer empId; + +} diff --git a/tooling/metamodel-generator/src/test/java/org/hibernate/processor/test/hhh18829/EmployeeWithIdClass.java b/tooling/metamodel-generator/src/test/java/org/hibernate/processor/test/hhh18829/EmployeeWithIdClass.java new file mode 100644 index 0000000000..fa5e80d7ce --- /dev/null +++ b/tooling/metamodel-generator/src/test/java/org/hibernate/processor/test/hhh18829/EmployeeWithIdClass.java @@ -0,0 +1,22 @@ +/* + * SPDX-License-Identifier: LGPL-2.1-or-later + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.processor.test.hhh18829; + +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.IdClass; + +@Entity +@IdClass(EmployeeWithIdClass.EmployeeId.class) +public class EmployeeWithIdClass extends Address { + @Id + String empName; + @Id + Integer empId; + + public record EmployeeId(String empName, Integer empId) { + } + +}