From 2878b44303da83f8d61d78bbe286097f0882984e Mon Sep 17 00:00:00 2001 From: Andrea Boriero Date: Mon, 29 Apr 2024 17:08:48 +0200 Subject: [PATCH] HHH-18028 Add test for issue --- .../AnnotationConverterAndEmbeddableTest.java | 156 +++++++++++++++++ ...AnnotationConverterAndEmbeddableTest2.java | 155 +++++++++++++++++ .../AnnotationConverterAndExceptionTest.java | 163 ++++++++++++++++++ 3 files changed, 474 insertions(+) create mode 100644 hibernate-core/src/test/java/org/hibernate/orm/test/jpa/compliance/AnnotationConverterAndEmbeddableTest.java create mode 100644 hibernate-core/src/test/java/org/hibernate/orm/test/jpa/compliance/AnnotationConverterAndEmbeddableTest2.java create mode 100644 hibernate-core/src/test/java/org/hibernate/orm/test/jpa/compliance/AnnotationConverterAndExceptionTest.java diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/compliance/AnnotationConverterAndEmbeddableTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/compliance/AnnotationConverterAndEmbeddableTest.java new file mode 100644 index 0000000000..42d1f53565 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/compliance/AnnotationConverterAndEmbeddableTest.java @@ -0,0 +1,156 @@ +package org.hibernate.orm.test.jpa.compliance; + +import java.util.List; + +import org.hibernate.testing.jdbc.SQLStatementInspector; +import org.hibernate.testing.orm.junit.EntityManagerFactoryScope; +import org.hibernate.testing.orm.junit.JiraKey; +import org.hibernate.testing.orm.junit.Jpa; +import org.junit.jupiter.api.Test; + +import jakarta.persistence.Access; +import jakarta.persistence.AccessType; +import jakarta.persistence.AttributeConverter; +import jakarta.persistence.Convert; +import jakarta.persistence.Converter; +import jakarta.persistence.Converts; +import jakarta.persistence.Embeddable; +import jakarta.persistence.Embedded; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +@Jpa( + annotatedClasses = { + AnnotationConverterAndEmbeddableTest.Person.class + }, + useCollectingStatementInspector = true +) +@JiraKey( "HHH-18028" ) +public class AnnotationConverterAndEmbeddableTest { + + private static final String EXPECTED_ERROR_MESSAGE = "Exception was thrown by IntegerToStringConverter"; + + @Test + public void testConverterIsCorrectlyApplied(EntityManagerFactoryScope scope) { + SQLStatementInspector sqlStatementInspector = (SQLStatementInspector) scope.getStatementInspector(); + sqlStatementInspector.clear(); + scope.inTransaction( + entityManager -> { + Person b = new Person( + 1, + "and n.", + new Address( "Localita S. Egidio n. 5", "Gradoli" ) + ); + entityManager.persist( b ); + } + ); + List sqlQueries = sqlStatementInspector.getSqlQueries(); + assertThat( sqlQueries.size() ).isEqualTo( 1 ); + sqlStatementInspector.assertIsInsert( 0 ); + String query = sqlQueries.get( 0 ); + assertThat( query.contains( "Localita S. Egidio # 5" ) ); + assertThat( query.contains( "and #" ) ); + } + + + @Entity(name = "Person") + @Converts( + value = { + @Convert(attributeName = "address.street", converter = AnnotationConverterAndEmbeddableTest.StreetConverter.class), + @Convert(attributeName = "name", converter = AnnotationConverterAndEmbeddableTest.StreetConverter.class), + } + ) + public static class Person { + + protected Integer id; + + protected String name; + + + protected Address address; + + public Person() { + } + + public Person(Integer id, String name, Address address) { + this.id = id; + this.name = name; + this.address = address; + } + + @Id + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + @Embedded + public Address getAddress() { + return address; + } + + public void setAddress(Address address) { + this.address = address; + } + } + + @Embeddable + @Access(AccessType.PROPERTY) + public static class Address { + + protected String street; + + protected String city; + + public Address() { + } + + public Address(String street, String city) { + this.street = street; + this.city = city; + } + + public String getCity() { + return city; + } + + public void setCity(String city) { + this.city = city; + } + + public String getStreet() { + return street; + } + + public void setStreet(String street) { + this.street = street; + } + + } + + @Converter + public static class StreetConverter implements AttributeConverter { + + public String convertToDatabaseColumn(String attribute) { + return attribute.replace( "n.", "#" ); + } + + public String convertToEntityAttribute(String dbData) { + return dbData.replace( "#", "n." ); + } + } + +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/compliance/AnnotationConverterAndEmbeddableTest2.java b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/compliance/AnnotationConverterAndEmbeddableTest2.java new file mode 100644 index 0000000000..614be555af --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/compliance/AnnotationConverterAndEmbeddableTest2.java @@ -0,0 +1,155 @@ +package org.hibernate.orm.test.jpa.compliance; + +import java.util.List; + +import org.hibernate.testing.jdbc.SQLStatementInspector; +import org.hibernate.testing.orm.junit.EntityManagerFactoryScope; +import org.hibernate.testing.orm.junit.JiraKey; +import org.hibernate.testing.orm.junit.Jpa; +import org.junit.jupiter.api.Test; + +import jakarta.persistence.Access; +import jakarta.persistence.AccessType; +import jakarta.persistence.AttributeConverter; +import jakarta.persistence.Convert; +import jakarta.persistence.Converter; +import jakarta.persistence.Converts; +import jakarta.persistence.Embeddable; +import jakarta.persistence.Embedded; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; + +@Jpa( + annotatedClasses = { + AnnotationConverterAndEmbeddableTest2.Person.class + }, + useCollectingStatementInspector = true +) +@JiraKey( "HHH-18028" ) +public class AnnotationConverterAndEmbeddableTest2 { + + private static final String EXPECTED_ERROR_MESSAGE = "Exception was thrown by IntegerToStringConverter"; + + @Test + public void testConverterIsCorrectlyApplied(EntityManagerFactoryScope scope) { + SQLStatementInspector sqlStatementInspector = (SQLStatementInspector) scope.getStatementInspector(); + sqlStatementInspector.clear(); + scope.inTransaction( + entityManager -> { + Person b = new Person( + 1, + "and n.", + new Address( "Localita S. Egidio n. 5", "Gradoli" ) + ); + entityManager.persist( b ); + } + ); + List sqlQueries = sqlStatementInspector.getSqlQueries(); + assertThat( sqlQueries.size() ).isEqualTo( 1 ); + sqlStatementInspector.assertIsInsert( 0 ); + String query = sqlQueries.get( 0 ); + assertThat( query.contains( "Localita S. Egidio # 5" ) ); + assertThat( query.contains( "and #" ) ); + } + + + @Entity(name = "Person") + @Converts( + value = { + @Convert(attributeName = "name", converter = AnnotationConverterAndEmbeddableTest2.StreetConverter.class), + } + ) + public static class Person { + + @Id + private Integer id; + + private String name; + + @Embedded + @Convert(attributeName = "street", converter = AnnotationConverterAndEmbeddableTest2.StreetConverter.class) + private Address address; + + public Person() { + } + + public Person(Integer id, String name, Address address) { + this.id = id; + this.name = name; + this.address = address; + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Address getAddress() { + return address; + } + + public void setAddress(Address address) { + this.address = address; + } + } + + @Embeddable + @Access(AccessType.PROPERTY) + public static class Address { + + private String street; + + private String city; + + public Address() { + } + + public Address(String street, String city) { + this.street = street; + this.city = city; + } + + public String getCity() { + return city; + } + + public void setCity(String city) { + this.city = city; + } + + public String getStreet() { + return street; + } + + public void setStreet(String street) { + this.street = street; + } + + } + + @Converter + public static class StreetConverter implements AttributeConverter { + + public String convertToDatabaseColumn(String attribute) { + return attribute.replace( "n.", "#" ); + } + + public String convertToEntityAttribute(String dbData) { + return dbData.replace( "#", "n." ); + } + } + +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/compliance/AnnotationConverterAndExceptionTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/compliance/AnnotationConverterAndExceptionTest.java new file mode 100644 index 0000000000..f3e87607f2 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/compliance/AnnotationConverterAndExceptionTest.java @@ -0,0 +1,163 @@ +package org.hibernate.orm.test.jpa.compliance; + +import org.hibernate.testing.orm.junit.EntityManagerFactoryScope; +import org.hibernate.testing.orm.junit.JiraKey; +import org.hibernate.testing.orm.junit.Jpa; +import org.junit.jupiter.api.Test; + +import jakarta.persistence.Access; +import jakarta.persistence.AccessType; +import jakarta.persistence.AttributeConverter; +import jakarta.persistence.Convert; +import jakarta.persistence.Converter; +import jakarta.persistence.Converts; +import jakarta.persistence.Embeddable; +import jakarta.persistence.Embedded; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.PersistenceException; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; + +@Jpa( + annotatedClasses = { + AnnotationConverterAndExceptionTest.Person.class + } +) +@JiraKey("HHH-18028") +public class AnnotationConverterAndExceptionTest { + + private static final String EXPECTED_ERROR_MESSAGE = "Exception was thrown by IntegerToStringConverter"; + + @Test + public void testExceptionThrownByConverterIsPropagated(EntityManagerFactoryScope scope) { + PersistenceException persistenceException = assertThrows( PersistenceException.class, () -> + scope.inEntityManager( + entityManager -> { + entityManager.getTransaction().begin(); + try { + Person b = new Person( + 1, + "and", + new Address( "Localita S. Egidio n. 5", "Gradoli" ) + ); + entityManager.persist( b ); + entityManager.flush(); + fail( "Persistence exception expected" ); + } + catch (PersistenceException pe) { + assertTrue( entityManager.getTransaction().getRollbackOnly() ); + throw pe; + } + finally { + if ( entityManager.getTransaction().isActive() ) { + entityManager.getTransaction().rollback(); + } + } + } + ) + ); + assertThat( persistenceException.getMessage() ).contains( EXPECTED_ERROR_MESSAGE ); + } + + + @Entity(name = "Person") + public static class Person { + + @Id + protected Integer id; + + protected String name; + + @Embedded + @Converts( + value = { + @Convert(attributeName = "street", converter = StreetConverter.class), + } + ) + protected Address address; + + public Person() { + } + + public Person(Integer id, String name, Address address) { + this.id = id; + this.name = name; + this.address = address; + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Address getAddress() { + return address; + } + + public void setAddress(Address address) { + this.address = address; + } + } + + @Embeddable + @Access(AccessType.PROPERTY) + public static class Address { + + protected String street; + + protected String city; + + public Address() { + } + + public Address(String street, String city) { + this.street = street; + this.city = city; + } + + public String getCity() { + return city; + } + + public void setCity(String city) { + this.city = city; + } + + public String getStreet() { + return street; + } + + public void setStreet(String street) { + this.street = street; + } + + } + + @Converter + public static class StreetConverter implements AttributeConverter { + + public String convertToDatabaseColumn(String attribute) { + throw new RuntimeException( EXPECTED_ERROR_MESSAGE ); + } + + public String convertToEntityAttribute(String dbData) { + return dbData.replace( "#", "n." ); + } + } + +}