From a10970c2cda4de534e293765512b15ddff9f011c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Kuruc?= Date: Sat, 19 Apr 2025 16:58:09 +0200 Subject: [PATCH 1/7] HHH-19372: Reproducing test --- .../HierarchyBytecodeOptimizerTest.java | 49 +++++++++++++++++++ .../enhancement/optimizer/ParentEntity.java | 35 +++++++++++++ .../optimizer/child/ChildEntity.java | 22 +++++++++ 3 files changed, 106 insertions(+) create mode 100644 hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/optimizer/HierarchyBytecodeOptimizerTest.java create mode 100644 hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/optimizer/ParentEntity.java create mode 100644 hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/optimizer/child/ChildEntity.java diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/optimizer/HierarchyBytecodeOptimizerTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/optimizer/HierarchyBytecodeOptimizerTest.java new file mode 100644 index 000000000000..65b8f1ce8a9b --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/optimizer/HierarchyBytecodeOptimizerTest.java @@ -0,0 +1,49 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.orm.test.bytecode.enhancement.optimizer; + +import org.hibernate.orm.test.bytecode.enhancement.optimizer.child.ChildEntity; +import org.hibernate.query.Query; + +import org.hibernate.testing.bytecode.enhancement.extension.BytecodeEnhanced; +import org.hibernate.testing.orm.junit.DomainModel; +import org.hibernate.testing.orm.junit.Jira; +import org.hibernate.testing.orm.junit.SessionFactory; +import org.hibernate.testing.orm.junit.SessionFactoryScope; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +@DomainModel(annotatedClasses = { + ParentEntity.class, + ChildEntity.class, +}) +@SessionFactory +@Jira( "https://hibernate.atlassian.net/browse/HHH-19059" ) +@BytecodeEnhanced +public class HierarchyBytecodeOptimizerTest { + + @Test + public void testOptimizerSetPropertyValues(SessionFactoryScope scope) { + ChildEntity childEntity = new ChildEntity(); + childEntity.setId( 1L ); + childEntity.setField( "field" ); + childEntity.setChieldField( "childField" ); + + scope.inTransaction( session -> session.persist( childEntity ) ); + + scope.inTransaction( session -> { + Query query = session.createQuery( "select c from ChildEntity c where c.field = :field", ChildEntity.class); + query.setParameter( "field", "field" ); + assertThat( query.uniqueResult() ).isNotNull(); + } ); + } + + @AfterAll + public void cleanup(SessionFactoryScope scope) { + scope.getSessionFactory().getSchemaManager().truncateMappedObjects(); + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/optimizer/ParentEntity.java b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/optimizer/ParentEntity.java new file mode 100644 index 000000000000..84a7f72690f3 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/optimizer/ParentEntity.java @@ -0,0 +1,35 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.orm.test.bytecode.enhancement.optimizer; + +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.Inheritance; +import jakarta.persistence.InheritanceType; + +@Entity(name = "ParentEntity") +@Inheritance(strategy = InheritanceType.JOINED) +public class ParentEntity { + @Id + private Long id; + + private String field; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getField() { + return field; + } + + public void setField(String field) { + this.field = field; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/optimizer/child/ChildEntity.java b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/optimizer/child/ChildEntity.java new file mode 100644 index 000000000000..d189fad30c9b --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/optimizer/child/ChildEntity.java @@ -0,0 +1,22 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.orm.test.bytecode.enhancement.optimizer.child; + +import org.hibernate.orm.test.bytecode.enhancement.optimizer.ParentEntity; + +import jakarta.persistence.Entity; + +@Entity(name = "ChildEntity") +public class ChildEntity extends ParentEntity { + private String childField; + + public String getChildField() { + return childField; + } + + public void setChieldField(String childField) { + this.childField = childField; + } +} From 0fa010dc9caca3a66e9690c996220d5eb78b8a6e Mon Sep 17 00:00:00 2001 From: Andrea Boriero Date: Wed, 23 Apr 2025 15:12:19 +0200 Subject: [PATCH 2/7] HHH-19369 Add test for issue --- .../enhancement/optimizer/AncestorEntity.java | 35 ++++++ .../enhancement/optimizer/ChildEntity3.java | 20 +++ .../enhancement/optimizer/ChildEntity4.java | 20 +++ .../enhancement/optimizer/ChildEntity5.java | 20 +++ .../enhancement/optimizer/ChildEntity6.java | 20 +++ .../enhancement/optimizer/ChildEntity7.java | 20 +++ .../enhancement/optimizer/ChildEntity8.java | 20 +++ .../enhancement/optimizer/ChildEntity9.java | 20 +++ ...BytecodeOptimizerMethodVisibilityTest.java | 68 +++++++++++ ...ierarchyBytecodeOptimizerOrderingTest.java | 115 ++++++++++++++++++ .../HierarchyBytecodeOptimizerTest.java | 11 +- .../enhancement/optimizer/ParentEntity.java | 3 +- .../optimizer/child/ChildEntity10.java | 21 ++++ .../optimizer/parent/Ancestor.java | 35 ++++++ .../optimizer/parent/ChildEntity2.java | 21 ++++ 15 files changed, 444 insertions(+), 5 deletions(-) create mode 100644 hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/optimizer/AncestorEntity.java create mode 100644 hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/optimizer/ChildEntity3.java create mode 100644 hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/optimizer/ChildEntity4.java create mode 100644 hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/optimizer/ChildEntity5.java create mode 100644 hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/optimizer/ChildEntity6.java create mode 100644 hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/optimizer/ChildEntity7.java create mode 100644 hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/optimizer/ChildEntity8.java create mode 100644 hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/optimizer/ChildEntity9.java create mode 100644 hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/optimizer/HierarchyBytecodeOptimizerMethodVisibilityTest.java create mode 100644 hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/optimizer/HierarchyBytecodeOptimizerOrderingTest.java create mode 100644 hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/optimizer/child/ChildEntity10.java create mode 100644 hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/optimizer/parent/Ancestor.java create mode 100644 hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/optimizer/parent/ChildEntity2.java diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/optimizer/AncestorEntity.java b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/optimizer/AncestorEntity.java new file mode 100644 index 000000000000..ab7cdffb8a4d --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/optimizer/AncestorEntity.java @@ -0,0 +1,35 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.orm.test.bytecode.enhancement.optimizer; + +import jakarta.persistence.Entity; +import jakarta.persistence.Inheritance; +import jakarta.persistence.InheritanceType; +import org.hibernate.orm.test.bytecode.enhancement.optimizer.parent.Ancestor; + +@Entity(name = "AncestorEntity") +@Inheritance(strategy = InheritanceType.JOINED) +public class AncestorEntity extends Ancestor { + + private Long id; + + private String field; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getField() { + return field; + } + + public void setField(String field) { + this.field = field; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/optimizer/ChildEntity3.java b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/optimizer/ChildEntity3.java new file mode 100644 index 000000000000..100191b43b98 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/optimizer/ChildEntity3.java @@ -0,0 +1,20 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.orm.test.bytecode.enhancement.optimizer; + +import jakarta.persistence.Entity; + +@Entity(name = "ChildEntity3") +public class ChildEntity3 extends AncestorEntity { + private String childField; + + public String getChildField() { + return childField; + } + + public void setChieldField(String childField) { + this.childField = childField; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/optimizer/ChildEntity4.java b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/optimizer/ChildEntity4.java new file mode 100644 index 000000000000..a8ed90f3ef5b --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/optimizer/ChildEntity4.java @@ -0,0 +1,20 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.orm.test.bytecode.enhancement.optimizer; + +import jakarta.persistence.Entity; + +@Entity(name = "ChildEntity4") +public class ChildEntity4 extends AncestorEntity { + private String childField; + + public String getChildField() { + return childField; + } + + public void setChieldField(String childField) { + this.childField = childField; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/optimizer/ChildEntity5.java b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/optimizer/ChildEntity5.java new file mode 100644 index 000000000000..ba7540fec1fa --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/optimizer/ChildEntity5.java @@ -0,0 +1,20 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.orm.test.bytecode.enhancement.optimizer; + +import jakarta.persistence.Entity; + +@Entity(name = "ChildEntity5") +public class ChildEntity5 extends AncestorEntity { + private String childField; + + public String getChildField() { + return childField; + } + + public void setChieldField(String childField) { + this.childField = childField; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/optimizer/ChildEntity6.java b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/optimizer/ChildEntity6.java new file mode 100644 index 000000000000..a996eb9089ed --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/optimizer/ChildEntity6.java @@ -0,0 +1,20 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.orm.test.bytecode.enhancement.optimizer; + +import jakarta.persistence.Entity; + +@Entity(name = "ChildEntity6") +public class ChildEntity6 extends AncestorEntity { + private String childField; + + public String getChildField() { + return childField; + } + + public void setChieldField(String childField) { + this.childField = childField; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/optimizer/ChildEntity7.java b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/optimizer/ChildEntity7.java new file mode 100644 index 000000000000..9a9775a53cd3 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/optimizer/ChildEntity7.java @@ -0,0 +1,20 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.orm.test.bytecode.enhancement.optimizer; + +import jakarta.persistence.Entity; + +@Entity(name = "ChildEntity7") +public class ChildEntity7 extends AncestorEntity { + private String childField; + + public String getChildField() { + return childField; + } + + public void setChildField(String childField) { + this.childField = childField; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/optimizer/ChildEntity8.java b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/optimizer/ChildEntity8.java new file mode 100644 index 000000000000..f6bdd29a2a29 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/optimizer/ChildEntity8.java @@ -0,0 +1,20 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.orm.test.bytecode.enhancement.optimizer; + +import jakarta.persistence.Entity; + +@Entity(name = "ChildEntity8") +public class ChildEntity8 extends AncestorEntity { + private String childField; + + public String getChildField() { + return childField; + } + + public void setChildField(String childField) { + this.childField = childField; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/optimizer/ChildEntity9.java b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/optimizer/ChildEntity9.java new file mode 100644 index 000000000000..b734abdd91ee --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/optimizer/ChildEntity9.java @@ -0,0 +1,20 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.orm.test.bytecode.enhancement.optimizer; + +import jakarta.persistence.Entity; + +@Entity(name = "ChildEntity9") +public class ChildEntity9 extends AncestorEntity { + private String childField; + + public String getChildField() { + return childField; + } + + public void setChildField(String childField) { + this.childField = childField; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/optimizer/HierarchyBytecodeOptimizerMethodVisibilityTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/optimizer/HierarchyBytecodeOptimizerMethodVisibilityTest.java new file mode 100644 index 000000000000..e6e9dd57eed4 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/optimizer/HierarchyBytecodeOptimizerMethodVisibilityTest.java @@ -0,0 +1,68 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.orm.test.bytecode.enhancement.optimizer; + +import org.hibernate.orm.test.bytecode.enhancement.optimizer.child.ChildEntity10; +import org.hibernate.orm.test.bytecode.enhancement.optimizer.parent.Ancestor; +import org.hibernate.orm.test.bytecode.enhancement.optimizer.parent.ChildEntity2; +import org.hibernate.query.Query; +import org.hibernate.testing.bytecode.enhancement.extension.BytecodeEnhanced; +import org.hibernate.testing.orm.junit.DomainModel; +import org.hibernate.testing.orm.junit.Jira; +import org.hibernate.testing.orm.junit.SessionFactory; +import org.hibernate.testing.orm.junit.SessionFactoryScope; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +@DomainModel(annotatedClasses = { + Ancestor.class, + AncestorEntity.class, + ChildEntity2.class, + ChildEntity10.class +}) +@SessionFactory +@Jira("https://hibernate.atlassian.net/browse/HHH-19372") +@BytecodeEnhanced +public class HierarchyBytecodeOptimizerMethodVisibilityTest { + + @Test + public void testOptimizerSetPropertyValues(SessionFactoryScope scope) { + ChildEntity2 childEntity2 = new ChildEntity2(); + childEntity2.setId( 1L ); + childEntity2.setField( "field" ); + childEntity2.setChieldField( "childField" ); + + ChildEntity10 childEntity10 = new ChildEntity10(); + childEntity10.setId( 3L ); + childEntity10.setField( "field10" ); + childEntity10.setChieldField( "childField3" ); + + scope.inTransaction( session -> { + session.persist( childEntity2 ); + session.persist( childEntity10 ); + } ); + + scope.inTransaction( session -> { + Query query = session.createQuery( "select c from ChildEntity2 c where c.field = :field", + ChildEntity2.class ); + query.setParameter( "field", "field" ); + assertThat( query.uniqueResult() ).isNotNull(); + } ); + + scope.inTransaction( session -> { + Query query = session.createQuery( "select c from ChildEntity10 c where c.field = :field", + ChildEntity10.class ); + query.setParameter( "field", "field10" ); + assertThat( query.uniqueResult() ).isNotNull(); + } ); + } + + @AfterAll + public void cleanup(SessionFactoryScope scope) { + scope.getSessionFactory().getSchemaManager().truncateMappedObjects(); + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/optimizer/HierarchyBytecodeOptimizerOrderingTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/optimizer/HierarchyBytecodeOptimizerOrderingTest.java new file mode 100644 index 000000000000..1493c992c53e --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/optimizer/HierarchyBytecodeOptimizerOrderingTest.java @@ -0,0 +1,115 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.orm.test.bytecode.enhancement.optimizer; + +import org.hibernate.orm.test.bytecode.enhancement.optimizer.parent.Ancestor; +import org.hibernate.query.Query; +import org.hibernate.testing.bytecode.enhancement.extension.BytecodeEnhanced; +import org.hibernate.testing.orm.junit.DomainModel; +import org.hibernate.testing.orm.junit.Jira; +import org.hibernate.testing.orm.junit.SessionFactory; +import org.hibernate.testing.orm.junit.SessionFactoryScope; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +@DomainModel(annotatedClasses = { + Ancestor.class, + ParentEntity.class, + ChildEntity3.class, + ChildEntity4.class, + ChildEntity5.class, + ChildEntity6.class, + ChildEntity7.class, + ChildEntity8.class, + ChildEntity9.class +}) +@SessionFactory +@Jira("https://hibernate.atlassian.net/browse/HHH-19369") +@BytecodeEnhanced +public class HierarchyBytecodeOptimizerOrderingTest { + + @Test + public void testOptimizerSetPropertyValues(SessionFactoryScope scope) { + ChildEntity3 childEntity3 = new ChildEntity3(); + childEntity3.setId( 3L ); + childEntity3.setName( "child3" ); + childEntity3.setField( "field3" ); + childEntity3.setChieldField( "childField3" ); + + ChildEntity4 childEntity4 = new ChildEntity4(); + childEntity4.setId( 4L ); + childEntity4.setName( "child4" ); + childEntity4.setField( "field4" ); + childEntity4.setChieldField( "childField4" ); + + ChildEntity5 childEntity5 = new ChildEntity5(); + childEntity5.setId( 5L ); + childEntity5.setName( "child5" ); + childEntity5.setField( "field5" ); + childEntity5.setChieldField( "childField5" ); + + ChildEntity6 childEntity6 = new ChildEntity6(); + childEntity6.setId( 6L ); + childEntity6.setName( "child6" ); + childEntity6.setField( "field6" ); + childEntity6.setChieldField( "childField6" ); + + ChildEntity7 childEntity7 = new ChildEntity7(); + childEntity7.setId( 7L ); + childEntity7.setName( "child7" ); + childEntity7.setField( "field7" ); + childEntity7.setChildField( "childField7" ); + + scope.inTransaction( session -> { + session.persist( childEntity3 ); + session.persist( childEntity4 ); + session.persist( childEntity5 ); + session.persist( childEntity6 ); + session.persist( childEntity7 ); + } ); + + scope.inTransaction( session -> { + Query query = session.createQuery( "select c from ChildEntity3 c where c.field = :field", + ChildEntity3.class ); + query.setParameter( "field", "field3" ); + assertThat( query.uniqueResult() ).isNotNull(); + } ); + + scope.inTransaction( session -> { + Query query = session.createQuery( "select c from ChildEntity4 c where c.field = :field", + ChildEntity4.class ); + query.setParameter( "field", "field4" ); + assertThat( query.uniqueResult() ).isNotNull(); + } ); + + scope.inTransaction( session -> { + Query query = session.createQuery( "select c from ChildEntity5 c where c.field = :field", + ChildEntity5.class ); + query.setParameter( "field", "field5" ); + assertThat( query.uniqueResult() ).isNotNull(); + } ); + + scope.inTransaction( session -> { + Query query = session.createQuery( "select c from ChildEntity6 c where c.field = :field", + ChildEntity6.class ); + query.setParameter( "field", "field6" ); + assertThat( query.uniqueResult() ).isNotNull(); + } ); + + scope.inTransaction( session -> { + Query query = session.createQuery( + "select c from ChildEntity7 c where c.field = :field", ChildEntity7.class ); + query.setParameter( "field", "field7" ); + assertThat( query.uniqueResult() ).isNotNull(); + } ); + } + + @AfterAll + public void cleanup(SessionFactoryScope scope) { + scope.getSessionFactory().getSchemaManager().truncateMappedObjects(); + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/optimizer/HierarchyBytecodeOptimizerTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/optimizer/HierarchyBytecodeOptimizerTest.java index 65b8f1ce8a9b..a90b07190ef3 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/optimizer/HierarchyBytecodeOptimizerTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/optimizer/HierarchyBytecodeOptimizerTest.java @@ -6,7 +6,6 @@ import org.hibernate.orm.test.bytecode.enhancement.optimizer.child.ChildEntity; import org.hibernate.query.Query; - import org.hibernate.testing.bytecode.enhancement.extension.BytecodeEnhanced; import org.hibernate.testing.orm.junit.DomainModel; import org.hibernate.testing.orm.junit.Jira; @@ -22,7 +21,7 @@ ChildEntity.class, }) @SessionFactory -@Jira( "https://hibernate.atlassian.net/browse/HHH-19059" ) +@Jira("https://hibernate.atlassian.net/browse/HHH-19372") @BytecodeEnhanced public class HierarchyBytecodeOptimizerTest { @@ -33,13 +32,17 @@ public void testOptimizerSetPropertyValues(SessionFactoryScope scope) { childEntity.setField( "field" ); childEntity.setChieldField( "childField" ); - scope.inTransaction( session -> session.persist( childEntity ) ); + scope.inTransaction( session -> { + session.persist( childEntity ); + } ); scope.inTransaction( session -> { - Query query = session.createQuery( "select c from ChildEntity c where c.field = :field", ChildEntity.class); + Query query = session.createQuery( "select c from ChildEntity c where c.field = :field", + ChildEntity.class ); query.setParameter( "field", "field" ); assertThat( query.uniqueResult() ).isNotNull(); } ); + } @AfterAll diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/optimizer/ParentEntity.java b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/optimizer/ParentEntity.java index 84a7f72690f3..ee933b160ed0 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/optimizer/ParentEntity.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/optimizer/ParentEntity.java @@ -11,7 +11,8 @@ @Entity(name = "ParentEntity") @Inheritance(strategy = InheritanceType.JOINED) -public class ParentEntity { +public class ParentEntity { + @Id private Long id; diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/optimizer/child/ChildEntity10.java b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/optimizer/child/ChildEntity10.java new file mode 100644 index 000000000000..f1a6756a8c20 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/optimizer/child/ChildEntity10.java @@ -0,0 +1,21 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.orm.test.bytecode.enhancement.optimizer.child; + +import jakarta.persistence.Entity; +import org.hibernate.orm.test.bytecode.enhancement.optimizer.AncestorEntity; + +@Entity(name = "ChildEntity10") +public class ChildEntity10 extends AncestorEntity { + private String childField; + + public String getChildField() { + return childField; + } + + public void setChieldField(String childField) { + this.childField = childField; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/optimizer/parent/Ancestor.java b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/optimizer/parent/Ancestor.java new file mode 100644 index 000000000000..15389f9b22fb --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/optimizer/parent/Ancestor.java @@ -0,0 +1,35 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.orm.test.bytecode.enhancement.optimizer.parent; + +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.Inheritance; +import jakarta.persistence.InheritanceType; + +@Entity(name = "Parent") +@Inheritance(strategy = InheritanceType.JOINED) +public class Ancestor { + @Id + private Long id; + + private String name; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/optimizer/parent/ChildEntity2.java b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/optimizer/parent/ChildEntity2.java new file mode 100644 index 000000000000..05e4917d8c9e --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/optimizer/parent/ChildEntity2.java @@ -0,0 +1,21 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.orm.test.bytecode.enhancement.optimizer.parent; + +import jakarta.persistence.Entity; +import org.hibernate.orm.test.bytecode.enhancement.optimizer.AncestorEntity; + +@Entity(name = "ChildEntity2") +public class ChildEntity2 extends AncestorEntity { + private String childField; + + public String getChildField() { + return childField; + } + + public void setChieldField(String childField) { + this.childField = childField; + } +} From 676c3f3b547ed20950d6416dbd9a62f3a294fe7d Mon Sep 17 00:00:00 2001 From: Andrea Boriero Date: Wed, 23 Apr 2025 15:13:36 +0200 Subject: [PATCH 3/7] HHH-19372 HHH-19369 Issues with access optimizer and inheritance --- .../internal/bytebuddy/BytecodeProviderImpl.java | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/bytecode/internal/bytebuddy/BytecodeProviderImpl.java b/hibernate-core/src/main/java/org/hibernate/bytecode/internal/bytebuddy/BytecodeProviderImpl.java index 6fc6de8e3af5..bfabcfcd6e7c 100644 --- a/hibernate-core/src/main/java/org/hibernate/bytecode/internal/bytebuddy/BytecodeProviderImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/bytecode/internal/bytebuddy/BytecodeProviderImpl.java @@ -305,17 +305,11 @@ private Class determineAccessOptimizerSuperClass(Class clazz, String[] pro for ( int i = 0; i < getters.length; i++ ) { final Member getter = getters[i]; final Member setter = setters[i]; - boolean found = false; if ( getter.getDeclaringClass() == foreignPackageClassInfo.clazz && !Modifier.isPublic( getter.getModifiers() ) ) { foreignPackageClassInfo.getters.add( getter ); - found = true; } if ( setter.getDeclaringClass() == foreignPackageClassInfo.clazz && !Modifier.isPublic( setter.getModifiers() ) ) { foreignPackageClassInfo.setters.add( setter ); - found = true; - } - if ( found ) { - foreignPackageClassInfo.propertyNames.add( propertyNames[i] ); } } if ( foreignPackageClassInfo.getters.isEmpty() && foreignPackageClassInfo.setters.isEmpty() ) { @@ -351,7 +345,7 @@ else if ( getter instanceof Method method ) { TypeDescription.Generic.OfNonGenericType.ForLoadedType.of( getterType ), - Opcodes.ACC_PROTECTED | Opcodes.ACC_STATIC + Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC ) .withParameter( foreignPackageClassInfo.clazz ) .intercept( @@ -377,7 +371,7 @@ else if ( setter instanceof Method method ) { builder = builder.defineMethod( "set_" + setter.getName(), TypeDescription.Generic.VOID, - Opcodes.ACC_PROTECTED | Opcodes.ACC_STATIC + Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC ) .withParameter( foreignPackageClassInfo.clazz ) .withParameter( setterType ) From 3001ee5f08bf37e4795ea9bd46d6ed07390b5035 Mon Sep 17 00:00:00 2001 From: Andrea Boriero Date: Wed, 23 Apr 2025 19:18:53 +0200 Subject: [PATCH 4/7] HHH-19372 HHH-19369 use LinkedHashMap for InflightMetadataCollector#entityBindingMap --- .../hibernate/boot/internal/InFlightMetadataCollectorImpl.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hibernate-core/src/main/java/org/hibernate/boot/internal/InFlightMetadataCollectorImpl.java b/hibernate-core/src/main/java/org/hibernate/boot/internal/InFlightMetadataCollectorImpl.java index 42a0b3a3c65f..614f0bbe0964 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/internal/InFlightMetadataCollectorImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/internal/InFlightMetadataCollectorImpl.java @@ -104,6 +104,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; +import java.util.LinkedHashMap; import java.util.List; import java.util.Locale; import java.util.Map; @@ -145,7 +146,7 @@ public class InFlightMetadataCollectorImpl private final UUID uuid; - private final Map entityBindingMap = new HashMap<>(); + private final Map entityBindingMap = new LinkedHashMap<>(); private final List composites = new ArrayList<>(); private final Map, Component> genericComponentsMap = new HashMap<>(); private final Map> embeddableSubtypes = new HashMap<>(); From 0c2f0de7d38f4d99e9e01180a282f2a8b9e5db5b Mon Sep 17 00:00:00 2001 From: Andrea Boriero Date: Wed, 30 Apr 2025 14:36:27 +0200 Subject: [PATCH 5/7] HHH-19372 HHH-19369 Add Code Source Location HashCode to proxy generated classes --- .../internal/bytebuddy/BasicProxyFactoryImpl.java | 3 ++- .../internal/bytebuddy/BytecodeProviderImpl.java | 9 +++++---- .../proxy/pojo/bytebuddy/ByteBuddyProxyHelper.java | 14 ++++++++++++++ 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/bytecode/internal/bytebuddy/BasicProxyFactoryImpl.java b/hibernate-core/src/main/java/org/hibernate/bytecode/internal/bytebuddy/BasicProxyFactoryImpl.java index 10c114fdf09f..bf1a1e268afe 100644 --- a/hibernate-core/src/main/java/org/hibernate/bytecode/internal/bytebuddy/BasicProxyFactoryImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/bytecode/internal/bytebuddy/BasicProxyFactoryImpl.java @@ -15,6 +15,7 @@ import net.bytebuddy.description.modifier.Visibility; import net.bytebuddy.dynamic.scaffold.subclass.ConstructorStrategy; +import org.hibernate.proxy.pojo.bytebuddy.ByteBuddyProxyHelper; public class BasicProxyFactoryImpl implements BasicProxyFactory { @@ -36,7 +37,7 @@ public BasicProxyFactoryImpl(final Class superClass, final Class interfaceClass, final Class superClassOrMainInterface = superClass != null ? superClass : interfaceClass; final ByteBuddyState.ProxyDefinitionHelpers helpers = byteBuddyState.getProxyDefinitionHelpers(); - final String proxyClassName = superClassOrMainInterface.getName() + "$" + PROXY_NAMING_SUFFIX; + final String proxyClassName = ByteBuddyProxyHelper.getClassNameWithSuffix( superClassOrMainInterface, PROXY_NAMING_SUFFIX ); this.proxyClass = byteBuddyState.loadBasicProxy( superClassOrMainInterface, proxyClassName, (byteBuddy, namingStrategy) -> helpers.appendIgnoreAlsoAtEnd( byteBuddy diff --git a/hibernate-core/src/main/java/org/hibernate/bytecode/internal/bytebuddy/BytecodeProviderImpl.java b/hibernate-core/src/main/java/org/hibernate/bytecode/internal/bytebuddy/BytecodeProviderImpl.java index bfabcfcd6e7c..31d5bcfb00b0 100644 --- a/hibernate-core/src/main/java/org/hibernate/bytecode/internal/bytebuddy/BytecodeProviderImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/bytecode/internal/bytebuddy/BytecodeProviderImpl.java @@ -148,7 +148,7 @@ public ReflectionOptimizer getReflectionOptimizer( fastClass = null; } else { - final String className = clazz.getName() + "$" + INSTANTIATOR_PROXY_NAMING_SUFFIX; + final String className = ByteBuddyProxyHelper.getClassNameWithSuffix( clazz, INSTANTIATOR_PROXY_NAMING_SUFFIX ); fastClass = byteBuddyState.load( clazz, className, (byteBuddy, namingStrategy) -> byteBuddy .with( namingStrategy ) .subclass( ReflectionOptimizer.InstantiationOptimizer.class ) @@ -210,7 +210,7 @@ public ReflectionOptimizer getReflectionOptimizer( fastClass = null; } else { - final String className = clazz.getName() + "$" + INSTANTIATOR_PROXY_NAMING_SUFFIX; + final String className = ByteBuddyProxyHelper.getClassNameWithSuffix( clazz, INSTANTIATOR_PROXY_NAMING_SUFFIX ); fastClass = byteBuddyState.load( clazz, className, (byteBuddy, namingStrategy) -> byteBuddy .with( namingStrategy ) .subclass( ReflectionOptimizer.InstantiationOptimizer.class ) @@ -236,7 +236,8 @@ public ReflectionOptimizer getReflectionOptimizer( final String[] propertyNames = propertyAccessMap.keySet().toArray( new String[0] ); final Class superClass = determineAccessOptimizerSuperClass( clazz, propertyNames, getters, setters ); - final String className = clazz.getName() + "$" + OPTIMIZER_PROXY_NAMING_SUFFIX + encodeName( propertyNames, getters, setters ); + final String className = ByteBuddyProxyHelper.getClassNameWithSuffix( clazz, OPTIMIZER_PROXY_NAMING_SUFFIX ) + + encodeName( propertyNames, getters, setters ); final Class bulkAccessor; if ( className.getBytes( StandardCharsets.UTF_8 ).length >= 0x10000 ) { // The JVM has a 64K byte limit on class name length, so fallback to random name if encoding exceeds that @@ -322,7 +323,7 @@ private Class determineAccessOptimizerSuperClass(Class clazz, String[] pro final ForeignPackageClassInfo foreignPackageClassInfo = foreignPackageClassInfos.get( i ); final Class newSuperClass = superClass; - final String className = foreignPackageClassInfo.clazz.getName() + "$" + OPTIMIZER_PROXY_NAMING_SUFFIX + encodeName( foreignPackageClassInfo.propertyNames, foreignPackageClassInfo.getters, foreignPackageClassInfo.setters ); + final String className = ByteBuddyProxyHelper.getClassNameWithSuffix( foreignPackageClassInfo.clazz, OPTIMIZER_PROXY_NAMING_SUFFIX ) + encodeName( foreignPackageClassInfo.propertyNames, foreignPackageClassInfo.getters, foreignPackageClassInfo.setters ); superClass = byteBuddyState.load( foreignPackageClassInfo.clazz, className, diff --git a/hibernate-core/src/main/java/org/hibernate/proxy/pojo/bytebuddy/ByteBuddyProxyHelper.java b/hibernate-core/src/main/java/org/hibernate/proxy/pojo/bytebuddy/ByteBuddyProxyHelper.java index 8d3767b2c1f4..29304b446e62 100644 --- a/hibernate-core/src/main/java/org/hibernate/proxy/pojo/bytebuddy/ByteBuddyProxyHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/proxy/pojo/bytebuddy/ByteBuddyProxyHelper.java @@ -6,6 +6,7 @@ import java.io.Serializable; import java.lang.reflect.Method; +import java.net.URL; import java.util.Collection; import java.util.Collections; import java.util.HashSet; @@ -185,4 +186,17 @@ private static Method resolveIdSetterMethod(SerializableProxy serializableProxy) ); } } + + public static String getClassNameWithSuffix(Class clazz, String suffix) { + return getClassNameWithCodeSourceLocationHashCode(clazz) + "$" + suffix; + } + + private static String getClassNameWithCodeSourceLocationHashCode(Class clazz) { + final java.security.CodeSource codeSource = clazz.getProtectionDomain().getCodeSource(); + if ( codeSource == null ) { + return clazz.getName(); + } + final URL url = codeSource.getLocation(); + return url == null ? clazz.getName() : clazz.getName() + url.toString().hashCode(); + } } From 3dfa0c20d79786e26e2462cc8decb7d471372cb4 Mon Sep 17 00:00:00 2001 From: Andrea Boriero Date: Wed, 30 Apr 2025 17:43:27 +0200 Subject: [PATCH 6/7] HHH-19372 HHH-19369 Add Code Source Location HashCode to proxy generated classes --- .../proxy/pojo/bytebuddy/ByteBuddyProxyHelper.java | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/proxy/pojo/bytebuddy/ByteBuddyProxyHelper.java b/hibernate-core/src/main/java/org/hibernate/proxy/pojo/bytebuddy/ByteBuddyProxyHelper.java index 29304b446e62..4215eca3feba 100644 --- a/hibernate-core/src/main/java/org/hibernate/proxy/pojo/bytebuddy/ByteBuddyProxyHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/proxy/pojo/bytebuddy/ByteBuddyProxyHelper.java @@ -54,7 +54,7 @@ public Class buildProxy( } Collections.addAll( key, interfaces ); - final String proxyClassName = persistentClass.getTypeName() + "$" + PROXY_NAMING_SUFFIX; + final String proxyClassName = getClassNameWithSuffix( persistentClass, persistentClass.getTypeName(), PROXY_NAMING_SUFFIX ); return byteBuddyState.loadProxy( persistentClass, proxyClassName, proxyBuilder( TypeDescription.ForLoadedType.of( persistentClass ), new TypeList.Generic.ForLoadedTypes( interfaces ) ) ); } @@ -187,16 +187,24 @@ private static Method resolveIdSetterMethod(SerializableProxy serializableProxy) } } + private static String getClassNameWithSuffix(Class clazz, String name, String suffix) { + return getClassNameWithCodeSourceLocationHashCode(clazz, name) + "$" + suffix; + } + public static String getClassNameWithSuffix(Class clazz, String suffix) { return getClassNameWithCodeSourceLocationHashCode(clazz) + "$" + suffix; } private static String getClassNameWithCodeSourceLocationHashCode(Class clazz) { + return getClassNameWithCodeSourceLocationHashCode( clazz, clazz.getName() ); + } + + private static String getClassNameWithCodeSourceLocationHashCode(Class clazz, String className) { final java.security.CodeSource codeSource = clazz.getProtectionDomain().getCodeSource(); if ( codeSource == null ) { - return clazz.getName(); + return className; } final URL url = codeSource.getLocation(); - return url == null ? clazz.getName() : clazz.getName() + url.toString().hashCode(); + return url == null ? className : className + url.toString().hashCode(); } } From c18efda65d524c176eb8a17b0893825c45b4b9ba Mon Sep 17 00:00:00 2001 From: Andrea Boriero Date: Wed, 30 Apr 2025 17:44:58 +0200 Subject: [PATCH 7/7] HHH-19372 HHH-19369 Issues with access optimizer and inheritance --- .../bytebuddy/BytecodeProviderImpl.java | 23 +++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/bytecode/internal/bytebuddy/BytecodeProviderImpl.java b/hibernate-core/src/main/java/org/hibernate/bytecode/internal/bytebuddy/BytecodeProviderImpl.java index 31d5bcfb00b0..094d1263bab3 100644 --- a/hibernate-core/src/main/java/org/hibernate/bytecode/internal/bytebuddy/BytecodeProviderImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/bytecode/internal/bytebuddy/BytecodeProviderImpl.java @@ -306,11 +306,26 @@ private Class determineAccessOptimizerSuperClass(Class clazz, String[] pro for ( int i = 0; i < getters.length; i++ ) { final Member getter = getters[i]; final Member setter = setters[i]; - if ( getter.getDeclaringClass() == foreignPackageClassInfo.clazz && !Modifier.isPublic( getter.getModifiers() ) ) { - foreignPackageClassInfo.getters.add( getter ); + boolean addPropertyname = false; + if ( getter.getDeclaringClass() == foreignPackageClassInfo.clazz ) { + if( !Modifier.isPublic( getter.getModifiers())) { + foreignPackageClassInfo.getters.add( getter ); + } + else { + addPropertyname = true; + } + } + if ( setter.getDeclaringClass() == foreignPackageClassInfo.clazz ) { + if(!Modifier.isPublic( setter.getModifiers() )) { + foreignPackageClassInfo.setters.add( setter ); + } + else { + addPropertyname = true; + } + } - if ( setter.getDeclaringClass() == foreignPackageClassInfo.clazz && !Modifier.isPublic( setter.getModifiers() ) ) { - foreignPackageClassInfo.setters.add( setter ); + if ( addPropertyname ) { + foreignPackageClassInfo.propertyNames.add( propertyNames[i] ); } } if ( foreignPackageClassInfo.getters.isEmpty() && foreignPackageClassInfo.setters.isEmpty() ) {