diff --git a/src/main/java/org/springframework/data/mapping/model/SimplePersistentPropertyPathAccessor.java b/src/main/java/org/springframework/data/mapping/model/SimplePersistentPropertyPathAccessor.java index c8e685941..6dd2aae28 100644 --- a/src/main/java/org/springframework/data/mapping/model/SimplePersistentPropertyPathAccessor.java +++ b/src/main/java/org/springframework/data/mapping/model/SimplePersistentPropertyPathAccessor.java @@ -29,6 +29,7 @@ import java.util.stream.Collectors; import org.springframework.core.CollectionFactory; import org.springframework.data.mapping.AccessOptions; import org.springframework.data.mapping.AccessOptions.GetOptions; +import org.springframework.data.mapping.AccessOptions.GetOptions.GetNulls; import org.springframework.data.mapping.AccessOptions.SetOptions; import org.springframework.data.mapping.AccessOptions.SetOptions.SetNulls; import org.springframework.data.mapping.MappingException; @@ -53,6 +54,8 @@ import org.springframework.util.Assert; @RequiredArgsConstructor class SimplePersistentPropertyPathAccessor implements PersistentPropertyPathAccessor { + private static final GetOptions DEFAULT_GET_OPTIONS = AccessOptions.defaultGetOptions(); + private final @NonNull PersistentPropertyAccessor delegate; /* @@ -81,7 +84,7 @@ class SimplePersistentPropertyPathAccessor implements PersistentPropertyPathA @Nullable @Override public Object getProperty(PersistentPropertyPath> path) { - return getProperty(path, AccessOptions.defaultGetOptions()); + return getProperty(path, DEFAULT_GET_OPTIONS); } /* @@ -151,7 +154,11 @@ class SimplePersistentPropertyPathAccessor implements PersistentPropertyPathA return; } - Object parent = parentPath.isEmpty() ? getBean() : getProperty(parentPath); + GetOptions lookupOptions = options.getNullHandling() != REJECT + ? DEFAULT_GET_OPTIONS.withNullValues(GetNulls.EARLY_RETURN) + : DEFAULT_GET_OPTIONS; + + Object parent = parentPath.isEmpty() ? getBean() : getProperty(parentPath, lookupOptions); if (parent == null) { handleNull(path, options.getNullHandling()); diff --git a/src/test/java/org/springframework/data/mapping/model/SimplePersistentPropertyPathAccessorUnitTests.java b/src/test/java/org/springframework/data/mapping/model/SimplePersistentPropertyPathAccessorUnitTests.java index 6e7b78043..ab1ab395a 100644 --- a/src/test/java/org/springframework/data/mapping/model/SimplePersistentPropertyPathAccessorUnitTests.java +++ b/src/test/java/org/springframework/data/mapping/model/SimplePersistentPropertyPathAccessorUnitTests.java @@ -86,6 +86,20 @@ class SimplePersistentPropertyPathAccessorUnitTests { }).doesNotThrowAnyException(); } + @Test // DATACMNS-1296 + void skipsIntermediateNullsWhenSettingNestedValues() { + + CustomerWrapperWrapper wrapper = new CustomerWrapperWrapper(null); + + PersistentPropertyPathAccessor accessor = getAccessor(wrapper); + PersistentPropertyPath path = context + .getPersistentPropertyPath("wrapper.customer.firstname", CustomerWrapperWrapper.class); + + assertThatCode(() -> { + accessor.setProperty(path, "Dave", AccessOptions.defaultSetOptions().skipNulls()); + }).doesNotThrowAnyException(); + } + private void assertFirstnamesSetFor(Customers customers, String path) { PersistentPropertyPath propertyPath = context.getPersistentPropertyPath(path, @@ -124,4 +138,9 @@ class SimplePersistentPropertyPathAccessorUnitTests { static class CustomerWrapper { Customer customer; } + + @AllArgsConstructor + static class CustomerWrapperWrapper { + CustomerWrapper wrapper; + } }