diff --git a/src/main/java/org/springframework/data/mapping/PersistentPropertyAccessor.java b/src/main/java/org/springframework/data/mapping/PersistentPropertyAccessor.java index f8569df5e..ece298a9f 100644 --- a/src/main/java/org/springframework/data/mapping/PersistentPropertyAccessor.java +++ b/src/main/java/org/springframework/data/mapping/PersistentPropertyAccessor.java @@ -71,9 +71,21 @@ public interface PersistentPropertyAccessor { getBean().getClass().getName())); } - PersistentPropertyAccessor accessor = leafProperty.getOwner().getPropertyAccessor(parent); + PersistentPropertyAccessor accessor = parent == getBean() // + ? this // + : leafProperty.getOwner().getPropertyAccessor(parent); accessor.setProperty(leafProperty, value); + + if (parentPath.isEmpty()) { + return; + } + + Object bean = accessor.getBean(); + + if (bean != parent) { + setProperty(parentPath, bean); + } } /** diff --git a/src/test/java/org/springframework/data/mapping/PersistentPropertyAccessorUnitTests.java b/src/test/java/org/springframework/data/mapping/PersistentPropertyAccessorUnitTests.java index 18a2aff49..f426ed4f3 100644 --- a/src/test/java/org/springframework/data/mapping/PersistentPropertyAccessorUnitTests.java +++ b/src/test/java/org/springframework/data/mapping/PersistentPropertyAccessorUnitTests.java @@ -17,12 +17,15 @@ package org.springframework.data.mapping; import static org.assertj.core.api.Assertions.*; +import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.Data; import lombok.Value; +import lombok.experimental.Wither; import org.junit.Test; import org.springframework.data.mapping.context.SampleMappingContext; +import org.springframework.data.mapping.context.SamplePersistentProperty; /** * @author Oliver Gierke @@ -90,6 +93,27 @@ public class PersistentPropertyAccessorUnitTests { .isThrownBy(() -> accessor.setProperty(path, "Oliver August")); } + @Test // DATACMNS-1322 + public void correctlyReplacesObjectInstancesWhenSettingPropertyPathOnImmutableObjects() { + + PersistentEntity entity = context.getPersistentEntity(Outer.class); + PersistentPropertyPath path = context.getPersistentPropertyPath("immutable.value", + entity.getType()); + + NestedImmutable immutable = new NestedImmutable("foo"); + Outer outer = new Outer(immutable); + + PersistentPropertyAccessor accessor = entity.getPropertyAccessor(outer); + accessor.setProperty(path, "bar"); + + Object result = accessor.getBean(); + + assertThat(result).isInstanceOfSatisfying(Outer.class, it -> { + assertThat(it.immutable).isNotSameAs(immutable); + assertThat(it).isNotSameAs(outer); + }); + } + @Value static class Order { Customer customer; @@ -100,4 +124,18 @@ public class PersistentPropertyAccessorUnitTests { static class Customer { String firstname; } + + // DATACMNS-1322 + + @Value + @Wither(AccessLevel.PACKAGE) + static class NestedImmutable { + String value; + } + + @Value + @Wither(AccessLevel.PACKAGE) + static class Outer { + NestedImmutable immutable; + } }