diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhance/internal/bytebuddy/DirtyCheckingWithEmbeddableExtendingMappedSuperclassTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhance/internal/bytebuddy/DirtyCheckingWithEmbeddableExtendingMappedSuperclassTest.java new file mode 100644 index 0000000000..134a32a694 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhance/internal/bytebuddy/DirtyCheckingWithEmbeddableExtendingMappedSuperclassTest.java @@ -0,0 +1,130 @@ +/* + * 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.bytecode.enhance.internal.bytebuddy; + +import java.util.List; + +import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner; +import org.hibernate.testing.bytecode.enhancement.EnhancementOptions; +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.hibernate.testing.orm.junit.JiraKey; +import org.junit.Test; +import org.junit.runner.RunWith; + +import jakarta.persistence.Embeddable; +import jakarta.persistence.Embedded; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.MappedSuperclass; +import jakarta.persistence.Tuple; + +import static org.assertj.core.api.Assertions.assertThat; + +@RunWith(BytecodeEnhancerRunner.class) +@EnhancementOptions(inlineDirtyChecking = true) +public class DirtyCheckingWithEmbeddableExtendingMappedSuperclassTest extends + BaseCoreFunctionalTestCase { + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[]{ + MyEntity.class + }; + } + + @JiraKey("HHH-17041") + @Test + public void testQueryEmbeddableFields() { + inTransaction( + session -> { + MyEntity myEntity = new MyEntity(1, "one"); + session.persist( myEntity ); + } + ); + inTransaction( + session -> { + List result = session.createQuery( "select m.embedded.text, m.embedded.name from MyEntity m", Tuple.class ).list(); + assertThat( result.size() ).isEqualTo( 1 ); + Tuple tuple = result.get( 0 ); + assertThat( tuple.get( 0 ) ).isEqualTo( "one" ); + assertThat( tuple.get( 1 ) ).isNull(); + + } + ); + } + + @MappedSuperclass + public static abstract class MyAbstractEmbeddable { + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } + + @Embeddable + public static class MyEmbeddable extends MyAbstractEmbeddable { + + private String text; + + public MyEmbeddable() { + } + + private MyEmbeddable(String text) { + this.text = text; + } + + public String getText() { + return text; + } + + public void setText(String text) { + this.text = text; + } + } + + + @Entity(name = "MyEntity") + public static class MyEntity { + + @Id + private Integer id; + + @Embedded + private MyEmbeddable embedded; + + public MyEmbeddable getEmbedded() { + return embedded; + } + + public void setEmbedded(MyEmbeddable embedded) { + this.embedded = embedded; + } + + public MyEntity() { + } + + private MyEntity(Integer id, String text) { + this.id = id; + setEmbedded( new MyEmbeddable( text ) ); + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + } + +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhance/internal/bytebuddy/DirtyCheckingWithEmbeddableNonVisibleGenericExtendsSerializableMappedSuperclassTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhance/internal/bytebuddy/DirtyCheckingWithEmbeddableNonVisibleGenericExtendsSerializableMappedSuperclassTest.java new file mode 100644 index 0000000000..dc62ae2f76 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhance/internal/bytebuddy/DirtyCheckingWithEmbeddableNonVisibleGenericExtendsSerializableMappedSuperclassTest.java @@ -0,0 +1,126 @@ +/* + * 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.bytecode.enhance.internal.bytebuddy; + +import java.io.Serializable; +import java.util.List; + +import org.hibernate.testing.bytecode.enhancement.BytecodeEnhancerRunner; +import org.hibernate.testing.bytecode.enhancement.EnhancementOptions; +import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; +import org.hibernate.testing.orm.junit.JiraKey; +import org.junit.Test; +import org.junit.runner.RunWith; + +import jakarta.persistence.Embeddable; +import jakarta.persistence.Embedded; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.MappedSuperclass; +import jakarta.persistence.Tuple; + +import static org.assertj.core.api.Assertions.assertThat; + +@RunWith(BytecodeEnhancerRunner.class) +@EnhancementOptions(inlineDirtyChecking = true) +public class DirtyCheckingWithEmbeddableNonVisibleGenericExtendsSerializableMappedSuperclassTest extends + BaseCoreFunctionalTestCase { + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[]{ + MyEntity.class + }; + } + + @JiraKey("HHH-17041") + @Test + public void testQueryEmbeddableFields() { + inTransaction( + session -> { + MyEntity myEntity = new MyEntity(1, "one"); + session.persist( myEntity ); + } + ); + inTransaction( + session -> { + List result = session.createQuery( "select m.embedded.text, m.embedded.name from MyEntity m", Tuple.class ).list(); + assertThat( result.size() ).isEqualTo( 1 ); + Tuple tuple = result.get( 0 ); + assertThat( tuple.get( 0 ) ).isEqualTo( "one" ); + assertThat( tuple.get( 1 ) ).isNull(); + + } + ); + } + + @MappedSuperclass + public static abstract class MyAbstractEmbeddable implements Serializable { + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } + + @Embeddable + public static class MyEmbeddable extends MyAbstractEmbeddable { + + private String text; + + public MyEmbeddable() { + } + + private MyEmbeddable(String text) { + this.text = text; + } + + public String getText() { + return text; + } + + public void setText(String text) { + this.text = text; + } + } + + + @MappedSuperclass + public static abstract class MyMappedSuperclass + extends MyNonVisibleGenericExtendsSerializableMappedSuperclass { + } + + @Entity(name = "MyEntity") + public static class MyEntity extends + MyMappedSuperclass { + + @Id + private Integer id; + + public MyEntity() { + } + + private MyEntity(Integer id, String text) { + this.id = id; + setEmbedded( new MyEmbeddable( text ) ); + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + } + +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhance/internal/bytebuddy/MyNonVisibleGenericExtendsSerializableMappedSuperclass.java b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhance/internal/bytebuddy/MyNonVisibleGenericExtendsSerializableMappedSuperclass.java new file mode 100644 index 0000000000..2b029a9a88 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhance/internal/bytebuddy/MyNonVisibleGenericExtendsSerializableMappedSuperclass.java @@ -0,0 +1,29 @@ +/* + * 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.bytecode.enhance.internal.bytebuddy; + +import java.io.Serializable; + +import jakarta.persistence.Embedded; +import jakarta.persistence.MappedSuperclass; + +// This class must not be nested in the test class, otherwise its private fields will be visible +// from subclasses and we won't reproduce the bug. +@MappedSuperclass +public abstract class MyNonVisibleGenericExtendsSerializableMappedSuperclass { + + @Embedded + private C embedded; + + public C getEmbedded() { + return embedded; + } + + public void setEmbedded(C embedded) { + this.embedded = embedded; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/component/EmbeddableAndGenericExtendingSerializableMappedSuperclassTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/component/EmbeddableAndGenericExtendingSerializableMappedSuperclassTest.java new file mode 100644 index 0000000000..9728f446c0 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/component/EmbeddableAndGenericExtendingSerializableMappedSuperclassTest.java @@ -0,0 +1,155 @@ +/* + * 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.component; + +import java.io.Serializable; + +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.Test; + +import jakarta.persistence.Column; +import jakarta.persistence.Embeddable; +import jakarta.persistence.Embedded; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.MappedSuperclass; + +@DomainModel( + annotatedClasses = { + EmbeddableAndGenericExtendingSerializableMappedSuperclassTest.MyEntity.class, + EmbeddableAndGenericExtendingSerializableMappedSuperclassTest.AnotherEntity.class, + } +) +@SessionFactory +public class EmbeddableAndGenericExtendingSerializableMappedSuperclassTest { + + @JiraKey("HHH-17041") + @Test + public void testQueryEmbeddableFields(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + session.createQuery( "select m.embedded.text, m.embedded.name from MyEntity m" ).list(); + } + ); + } + + @MappedSuperclass + public static abstract class MyAbstractEmbeddable implements Serializable { + @Column + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } + + + @Embeddable + public static class MyEmbeddable extends MyAbstractEmbeddable { + + @Column + private String text; + + public MyEmbeddable() { + } + + private MyEmbeddable(String text) { + this.text = text; + } + + public String getText() { + return text; + } + + public void setText(String text) { + this.text = text; + } + } + + @Embeddable + public static class AnotherEmbeddable { + + @Column + private String value; + + public AnotherEmbeddable() { + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + } + + @MappedSuperclass + public static abstract class MyMappedSuperclass { + @Embedded + private C embedded; + + public C getEmbedded() { + return embedded; + } + + public void setEmbedded(C embedded) { + this.embedded = embedded; + } + } + + @Entity(name = "MyEntity") + public static class MyEntity extends MyMappedSuperclass { + + @Id + private Integer id; + + public MyEntity() { + } + + private MyEntity(Integer id, String text) { + this.id = id; + setEmbedded( new MyEmbeddable( text ) ); + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + } + + @Entity(name = "AnotherEntity") + public static class AnotherEntity extends MyMappedSuperclass { + + @Id + private Integer id; + + public AnotherEntity() { + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + } + +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/component/EmbeddableAndGenericMappedSuperclass2Test.java b/hibernate-core/src/test/java/org/hibernate/orm/test/component/EmbeddableAndGenericMappedSuperclass2Test.java new file mode 100644 index 0000000000..cd050fb277 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/component/EmbeddableAndGenericMappedSuperclass2Test.java @@ -0,0 +1,153 @@ +/* + * 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.component; + +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.Test; + +import jakarta.persistence.Column; +import jakarta.persistence.Embeddable; +import jakarta.persistence.Embedded; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.MappedSuperclass; + +@DomainModel( + annotatedClasses = { + EmbeddableAndGenericMappedSuperclass2Test.MyEntity.class, + EmbeddableAndGenericMappedSuperclass2Test.AnotherEntity.class, + } +) +@SessionFactory +public class EmbeddableAndGenericMappedSuperclass2Test { + + @JiraKey("HHH-17041") + @Test + public void testQueryEmbeddableFields(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + session.createQuery( "select m.embedded.text, m.embedded.name from MyEntity m" ).list(); + } + ); + } + + @MappedSuperclass + public static abstract class MyAbstractEmbeddable { + @Column + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } + + + @Embeddable + public static class MyEmbeddable extends MyAbstractEmbeddable { + + @Column + private String text; + + public MyEmbeddable() { + } + + private MyEmbeddable(String text) { + this.text = text; + } + + public String getText() { + return text; + } + + public void setText(String text) { + this.text = text; + } + } + + @Embeddable + public static class AnotherEmbeddable { + + @Column + private String value; + + public AnotherEmbeddable() { + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + } + + @MappedSuperclass + public static abstract class MyMappedSuperclass { + @Embedded + private C embedded; + + public C getEmbedded() { + return embedded; + } + + public void setEmbedded(C embedded) { + this.embedded = embedded; + } + } + + @Entity(name = "MyEntity") + public static class MyEntity extends MyMappedSuperclass { + + @Id + private Integer id; + + public MyEntity() { + } + + private MyEntity(Integer id, String text) { + this.id = id; + setEmbedded( new MyEmbeddable( text ) ); + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + } + + @Entity(name = "AnotherEntity") + public static class AnotherEntity extends MyMappedSuperclass { + + @Id + private Integer id; + + public AnotherEntity() { + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + } + +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/component/EmbeddableAndGenericMappedSuperclassTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/component/EmbeddableAndGenericMappedSuperclassTest.java new file mode 100644 index 0000000000..8599c84c00 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/component/EmbeddableAndGenericMappedSuperclassTest.java @@ -0,0 +1,113 @@ +/* + * 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.component; + +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.Test; + +import jakarta.persistence.Column; +import jakarta.persistence.Embeddable; +import jakarta.persistence.Embedded; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.MappedSuperclass; + +@DomainModel( + annotatedClasses = { EmbeddableAndGenericMappedSuperclassTest.MyEntity.class } +) +@SessionFactory +public class EmbeddableAndGenericMappedSuperclassTest { + + @JiraKey("HHH-17041") + @Test + public void testQueryEmbeddableFields(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + session.createQuery( "select m.embedded.text, m.embedded.name from MyEntity m" ).list(); + } + ); + } + + @MappedSuperclass + public static abstract class MyAbstractEmbeddable { + @Column + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } + + + @Embeddable + public static class MyEmbeddable extends MyAbstractEmbeddable { + + @Column + private String text; + + public MyEmbeddable() { + } + + private MyEmbeddable(String text) { + this.text = text; + } + + public String getText() { + return text; + } + + public void setText(String text) { + this.text = text; + } + } + + @MappedSuperclass + public static abstract class MyMappedSuperclass { + @Embedded + private C embedded; + + public C getEmbedded() { + return embedded; + } + + public void setEmbedded(C embedded) { + this.embedded = embedded; + } + } + + @Entity(name = "MyEntity") + public static class MyEntity extends MyMappedSuperclass { + + @Id + private Integer id; + + public MyEntity() { + } + + private MyEntity(Integer id, String text) { + this.id = id; + setEmbedded( new MyEmbeddable( text ) ); + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + } + +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/component/EmbeddableExtendsMappedSuperclassTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/component/EmbeddableExtendsMappedSuperclassTest.java new file mode 100644 index 0000000000..61962d4c7f --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/component/EmbeddableExtendsMappedSuperclassTest.java @@ -0,0 +1,106 @@ +/* + * 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.component; + +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.Test; + +import jakarta.persistence.Embeddable; +import jakarta.persistence.Embedded; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.MappedSuperclass; + +@DomainModel( + annotatedClasses = { EmbeddableExtendsMappedSuperclassTest.MyEntity.class } +) +@SessionFactory +public class EmbeddableExtendsMappedSuperclassTest { + + @JiraKey("HHH-17041") + @Test + public void testQueryEmbeddableFields(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + session.createQuery( "select m.embedded.text, m.embedded.name from MyEntity m" ).list(); + } + ); + } + + @MappedSuperclass + public static abstract class MyAbstractEmbeddable { + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } + + @Embeddable + public static class MyEmbeddable extends MyAbstractEmbeddable { + + private String text; + + public MyEmbeddable() { + } + + private MyEmbeddable(String text) { + this.text = text; + } + + public String getText() { + return text; + } + + public void setText(String text) { + this.text = text; + } + } + + + @Entity(name = "MyEntity") + public static class MyEntity { + + @Id + private Integer id; + + @Embedded + private MyEmbeddable embedded; + + public MyEmbeddable getEmbedded() { + return embedded; + } + + public void setEmbedded(MyEmbeddable embedded) { + this.embedded = embedded; + } + + public MyEntity() { + } + + private MyEntity(Integer id, String text) { + this.id = id; + setEmbedded( new MyEmbeddable( text ) ); + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + } +}