DATACMNS-1322 - Add support for immutable entities in PersistentPropertyAccessor.setProperty(PersistentPropertyPath, Object).

As setting a PersistentProperty can actually change the object that the property is changed on, we now recursively traverse property paths up as longs as the setting of the property results in the bean not being replaced.
This commit is contained in:
Oliver Gierke
2018-06-18 16:49:01 +02:00
parent 6cb3587ba3
commit d1ebfcfc5e
2 changed files with 51 additions and 1 deletions

View File

@@ -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);
}
}
/**

View File

@@ -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<Object, SamplePersistentProperty> entity = context.getPersistentEntity(Outer.class);
PersistentPropertyPath<SamplePersistentProperty> 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;
}
}