From e024bd0568d51777cb95004c109c00307ace0d9f Mon Sep 17 00:00:00 2001 From: Christian Beikov Date: Sat, 26 Oct 2024 16:04:19 +0200 Subject: [PATCH] HHH-18773 Deduplicate result initializers to avoid double initialization issues --- .../JdbcValuesMappingResolutionImpl.java | 4 +- ...ectJoinedAssociationMultipleTimesTest.java | 58 +++++++++++++++++++ 2 files changed, 60 insertions(+), 2 deletions(-) create mode 100644 hibernate-core/src/test/java/org/hibernate/orm/test/query/SelectJoinedAssociationMultipleTimesTest.java diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/jdbc/internal/JdbcValuesMappingResolutionImpl.java b/hibernate-core/src/main/java/org/hibernate/sql/results/jdbc/internal/JdbcValuesMappingResolutionImpl.java index a0ee9cb2c1..dbdcb058fe 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/jdbc/internal/JdbcValuesMappingResolutionImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/jdbc/internal/JdbcValuesMappingResolutionImpl.java @@ -4,7 +4,7 @@ */ package org.hibernate.sql.results.jdbc.internal; -import java.util.ArrayList; +import java.util.LinkedHashSet; import org.hibernate.sql.results.graph.DomainResultAssembler; import org.hibernate.sql.results.graph.Initializer; @@ -37,7 +37,7 @@ public class JdbcValuesMappingResolutionImpl implements JdbcValuesMappingResolut } private static Initializer[] getResultInitializers(DomainResultAssembler[] resultAssemblers) { - final ArrayList> initializers = new ArrayList<>( resultAssemblers.length ); + final LinkedHashSet> initializers = new LinkedHashSet<>( resultAssemblers.length ); for ( DomainResultAssembler resultAssembler : resultAssemblers ) { resultAssembler.forEachResultAssembler( (initializer, list) -> list.add( initializer ), initializers ); } diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/query/SelectJoinedAssociationMultipleTimesTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/query/SelectJoinedAssociationMultipleTimesTest.java new file mode 100644 index 0000000000..a244cfdd06 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/query/SelectJoinedAssociationMultipleTimesTest.java @@ -0,0 +1,58 @@ +/* + * SPDX-License-Identifier: LGPL-2.1-or-later + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.orm.test.query; + +import org.hibernate.testing.orm.junit.DomainModel; +import org.hibernate.testing.orm.junit.SessionFactory; +import org.hibernate.testing.orm.junit.SessionFactoryScope; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import jakarta.persistence.Entity; +import jakarta.persistence.Id; + +@DomainModel(annotatedClasses = { + SelectJoinedAssociationMultipleTimesTest.Book.class +}) +@SessionFactory +public class SelectJoinedAssociationMultipleTimesTest { + + @Test + public void test(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + // Add a proxy first to trigger the error + session.getReference( Book.class, 1 ); + session.createSelectionQuery( "select b b1, b b2 from Book b", Object[].class ).getResultList(); + } + ); + } + + @BeforeEach + public void prepareTestData(SessionFactoryScope scope) { + scope.inTransaction( (session) -> session.persist( new Book( 1, "First book" ) ) ); + } + + @AfterEach + public void dropTestData(SessionFactoryScope scope) { + scope.inTransaction( (session) -> session.createMutationQuery( "delete Book" ).executeUpdate() ); + } + + @Entity( name = "Book") + public static class Book { + @Id + private Integer id; + private String name; + + public Book() { + } + + public Book(Integer id, String name) { + this.id = id; + this.name = name; + } + } +}