From 1433423c1bf539073250c1a8787eef35999ac600 Mon Sep 17 00:00:00 2001 From: Yanming Zhou Date: Mon, 6 May 2024 15:13:13 +0800 Subject: [PATCH] HHH-18073 `BasicCollectionJavaType::wrap` should retain order of `Set` to keep consistent with `deepCopy` --- .../java/spi/BasicCollectionJavaType.java | 5 ++ ...BasicCollectionJavaTypeDescriptorTest.java | 68 +++++++++++++++++++ 2 files changed, 73 insertions(+) create mode 100644 hibernate-core/src/test/java/org/hibernate/orm/test/mapping/type/java/BasicCollectionJavaTypeDescriptorTest.java diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/BasicCollectionJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/BasicCollectionJavaType.java index fd8107805f..defc19dd8e 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/BasicCollectionJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/spi/BasicCollectionJavaType.java @@ -13,6 +13,7 @@ import java.sql.SQLException; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; +import java.util.LinkedHashSet; import org.hibernate.HibernateException; import org.hibernate.Incubating; @@ -445,6 +446,10 @@ public class BasicCollectionJavaType, E> extends Abstrac private C fromCollection(Collection value) { switch ( semantics.getCollectionClassification() ) { + case SET: + // Keep consistent with CollectionMutabilityPlan::deepCopy + //noinspection unchecked + return (C) new LinkedHashSet<>( value ); case LIST: case BAG: if ( value instanceof ArrayList ) { diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/type/java/BasicCollectionJavaTypeDescriptorTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/type/java/BasicCollectionJavaTypeDescriptorTest.java new file mode 100644 index 0000000000..db57d8c773 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/type/java/BasicCollectionJavaTypeDescriptorTest.java @@ -0,0 +1,68 @@ +/* + * 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.mapping.type.java; + +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; +import org.hibernate.collection.internal.StandardSetSemantics; +import org.hibernate.testing.orm.junit.JiraKey; +import org.hibernate.type.descriptor.java.StringJavaType; +import org.hibernate.type.descriptor.java.spi.BasicCollectionJavaType; +import org.junit.Test; + +import java.lang.reflect.ParameterizedType; +import java.util.LinkedHashSet; +import java.util.Set; + +import static org.junit.Assert.assertTrue; + +/** + * @author Yanming Zhou + */ +public class BasicCollectionJavaTypeDescriptorTest { + + private static final BasicCollectionJavaType, String> stringSetJavaType = createJavaType(); + + @Test + @JiraKey( "HHH-18073" ) + public void wrapShouldRetainOrderOfSet() { + assertTrue("BasicCollectionJavaType.wrap() should retain order of Set", + stringSetJavaType.wrap(Set.of( "foo", "bar" ), null) instanceof LinkedHashSet); + } + + @Test + public void deepCopyShouldRetainOrderOfSet() { + assertTrue("BasicCollectionJavaType.getMutabilityPlan().deepCopy() should retain order of Set", + stringSetJavaType.getMutabilityPlan().deepCopy(Set.of( "foo", "bar" )) instanceof LinkedHashSet); + } + + @SuppressWarnings("unchecked") + private static BasicCollectionJavaType, String> createJavaType() { + ParameterizedType type; + try { + type = (ParameterizedType) TestEntity.class.getDeclaredField("tags").getGenericType(); + } catch (NoSuchFieldException e) { + throw new RuntimeException(e); + } + return new BasicCollectionJavaType<>( + type, + StringJavaType.INSTANCE, + (StandardSetSemantics) StandardSetSemantics.INSTANCE + ); + } + + @Entity + static class TestEntity { + + @Id + @GeneratedValue + Long id; + + Set tags; + } +}