From 5ddede10b02aae7408c20d87105c5bbcb39d48f7 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Tue, 6 Aug 2024 15:14:18 +0200 Subject: [PATCH] Fix KotlinCopyMethod detection for single-association property classes. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit KotlinCopyMethod.shouldUsePublicCopyMethod(…) now considers single-association arrangements. Also, the method now early exists if pre-conditions aren't met. Closes #3131 --- .../data/mapping/model/KotlinCopyMethod.java | 4 +++- .../KotlinPropertyAccessorFactoryTests.java | 22 +++++++++++++++++++ .../data/mapping/model/DataClasses.kt | 15 +++++++++++++ 3 files changed, 40 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/springframework/data/mapping/model/KotlinCopyMethod.java b/src/main/java/org/springframework/data/mapping/model/KotlinCopyMethod.java index 951f295067..973d736262 100644 --- a/src/main/java/org/springframework/data/mapping/model/KotlinCopyMethod.java +++ b/src/main/java/org/springframework/data/mapping/model/KotlinCopyMethod.java @@ -38,6 +38,7 @@ import org.springframework.core.ResolvableType; import org.springframework.data.mapping.PersistentEntity; import org.springframework.data.mapping.PersistentProperty; +import org.springframework.data.mapping.SimpleAssociationHandler; import org.springframework.data.mapping.SimplePropertyHandler; import org.springframework.data.util.KotlinReflectionUtils; import org.springframework.util.Assert; @@ -158,8 +159,9 @@ boolean shouldUsePublicCopyMethod(PersistentEntity entity) { List> persistentProperties = new ArrayList<>(); entity.doWithProperties((SimplePropertyHandler) persistentProperties::add); + entity.doWithAssociations((SimpleAssociationHandler) it -> persistentProperties.add(it.getInverse())); - if (persistentProperties.size() > 1) { + if (persistentProperties.size() != 1) { return false; } diff --git a/src/test/java/org/springframework/data/mapping/model/KotlinPropertyAccessorFactoryTests.java b/src/test/java/org/springframework/data/mapping/model/KotlinPropertyAccessorFactoryTests.java index ced816abdf..3a11272234 100644 --- a/src/test/java/org/springframework/data/mapping/model/KotlinPropertyAccessorFactoryTests.java +++ b/src/test/java/org/springframework/data/mapping/model/KotlinPropertyAccessorFactoryTests.java @@ -25,6 +25,7 @@ import java.util.function.Function; import java.util.stream.Stream; +import org.jmolecules.ddd.types.Association; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; import org.springframework.beans.BeanUtils; @@ -283,6 +284,27 @@ void shouldUnwrapValueTypeIfNecessary(PersistentPropertyAccessorFactory factory) propertyAccessor.setProperty(createdBy, BeanUtils.instantiateClass(declaredConstructor, "baz")); } + @MethodSource("factories") + @ParameterizedTest // GH-3131 + void shouldApplyCopyForSinglePropertyClass(PersistentPropertyAccessorFactory factory) { + + BasicPersistentEntity entity = mappingContext + .getRequiredPersistentEntity(DataClassWithAssociation.class); + + var foo = Association.forAggregate(new DataClassAggregate(new DataClassId("foo"))); + var bar = Association.forAggregate(new DataClassAggregate(new DataClassId("bar"))); + Object instance = createInstance(entity, parameter -> foo); + + var propertyAccessor = factory.getPropertyAccessor(entity, instance); + var persistentProperty = entity.getRequiredPersistentProperty("assoc"); + + assertThat(propertyAccessor).isNotNull(); + assertThat(propertyAccessor.getProperty(persistentProperty)).isEqualTo(foo); + + propertyAccessor.setProperty(persistentProperty, bar); + assertThat(propertyAccessor.getProperty(persistentProperty)).isEqualTo(bar); + } + private Object createInstance(BasicPersistentEntity entity, Function, Object> parameterProvider) { return instantiators.getInstantiatorFor(entity).createInstance(entity, diff --git a/src/test/kotlin/org/springframework/data/mapping/model/DataClasses.kt b/src/test/kotlin/org/springframework/data/mapping/model/DataClasses.kt index d27659f6e9..e5627e1242 100644 --- a/src/test/kotlin/org/springframework/data/mapping/model/DataClasses.kt +++ b/src/test/kotlin/org/springframework/data/mapping/model/DataClasses.kt @@ -15,6 +15,8 @@ */ package org.springframework.data.mapping.model +import org.jmolecules.ddd.types.AggregateRoot +import org.jmolecules.ddd.types.Identifier import org.springframework.data.annotation.Id import java.time.LocalDateTime @@ -36,6 +38,19 @@ data class DataClassWithLazy( val foo by lazy { 123 } } +data class DataClassWithAssociation( + val assoc: org.jmolecules.ddd.types.Association +) + +data class DataClassId(val id: String) : Identifier { + +} + +data class DataClassAggregate(val identifier: DataClassId) : + AggregateRoot { + override fun getId() = this.identifier +} + data class SingleSettableProperty constructor(val id: Double = Math.random()) { val version: Int? = null }