diff --git a/src/main/java/org/springframework/data/mapping/PersistentEntity.java b/src/main/java/org/springframework/data/mapping/PersistentEntity.java index a919e39fd..94ddc102f 100644 --- a/src/main/java/org/springframework/data/mapping/PersistentEntity.java +++ b/src/main/java/org/springframework/data/mapping/PersistentEntity.java @@ -316,4 +316,13 @@ public interface PersistentEntity> extends It * @since 2.1 */ boolean isImmutable(); + + /** + * Returns whether the entity needs properties to be populated, i.e. if any property exists that's not initialized by + * the constructor. + * + * @return + * @since 2.1 + */ + boolean requiresPropertyPopulation(); } diff --git a/src/main/java/org/springframework/data/mapping/model/BasicPersistentEntity.java b/src/main/java/org/springframework/data/mapping/model/BasicPersistentEntity.java index 3a8589fcc..774e4f7be 100644 --- a/src/main/java/org/springframework/data/mapping/model/BasicPersistentEntity.java +++ b/src/main/java/org/springframework/data/mapping/model/BasicPersistentEntity.java @@ -95,6 +95,7 @@ public class BasicPersistentEntity> implement private final Lazy typeAlias; private final Lazy isNewStrategy; private final Lazy isImmutable; + private final Lazy requiresPropertyPopulation; /** * Creates a new {@link BasicPersistentEntity} from the given {@link TypeInformation}. @@ -134,6 +135,8 @@ public class BasicPersistentEntity> implement : getFallbackIsNewStrategy()); this.isImmutable = Lazy.of(() -> isAnnotationPresent(Immutable.class)); + this.requiresPropertyPopulation = Lazy.of(() -> !isImmutable() && properties.stream() // + .anyMatch(it -> !(isConstructorArgument(it) || it.isTransient()))); } /* @@ -508,6 +511,15 @@ public class BasicPersistentEntity> implement return isImmutable.get(); } + /* + * (non-Javadoc) + * @see org.springframework.data.mapping.PersistentEntity#requiresPropertyPopulation() + */ + @Override + public boolean requiresPropertyPopulation() { + return requiresPropertyPopulation.get(); + } + /* * (non-Javadoc) * @see java.lang.Iterable#iterator() diff --git a/src/test/java/org/springframework/data/mapping/model/BasicPersistentEntityUnitTests.java b/src/test/java/org/springframework/data/mapping/model/BasicPersistentEntityUnitTests.java index 632b765c1..88672ea24 100755 --- a/src/test/java/org/springframework/data/mapping/model/BasicPersistentEntityUnitTests.java +++ b/src/test/java/org/springframework/data/mapping/model/BasicPersistentEntityUnitTests.java @@ -19,6 +19,8 @@ import static org.assertj.core.api.Assertions.*; import static org.junit.Assume.*; import static org.mockito.Mockito.*; +import lombok.RequiredArgsConstructor; + import java.lang.annotation.Annotation; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -27,6 +29,7 @@ import java.util.Iterator; import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.stream.Stream; import org.hamcrest.CoreMatchers; import org.junit.Rule; @@ -44,6 +47,7 @@ import org.springframework.data.annotation.CreatedDate; import org.springframework.data.annotation.Immutable; import org.springframework.data.annotation.LastModifiedBy; import org.springframework.data.annotation.Persistent; +import org.springframework.data.annotation.Transient; import org.springframework.data.annotation.TypeAlias; import org.springframework.data.domain.Persistable; import org.springframework.data.mapping.Alias; @@ -355,6 +359,19 @@ public class BasicPersistentEntityUnitTests> { assertThat(createEntity(Entity.class).isImmutable()).isFalse(); } + @Test // DATACMNS-1366 + public void exposesPropertyPopulationRequired() { + + assertThat(createPopulatedPersistentEntity(PropertyPopulationRequired.class).requiresPropertyPopulation()).isTrue(); + } + + @Test // DATACMNS-1366 + public void exposesPropertyPopulationNotRequired() { + + Stream.of(PropertyPopulationNotRequired.class, PropertyPopulationNotRequiredWithTransient.class) // + .forEach(it -> assertThat(createPopulatedPersistentEntity(it).requiresPropertyPopulation()).isFalse()); + } + private BasicPersistentEntity createEntity(Class type) { return createEntity(type, null); } @@ -363,6 +380,12 @@ public class BasicPersistentEntityUnitTests> { return new BasicPersistentEntity<>(ClassTypeInformation.from(type), comparator); } + private static PersistentEntity createPopulatedPersistentEntity(Class type) { + + SampleMappingContext context = new SampleMappingContext(); + return context.getRequiredPersistentEntity(type); + } + @TypeAlias("foo") static class AliasedEntity { @@ -427,4 +450,26 @@ public class BasicPersistentEntityUnitTests> { @Immutable static class SomeValue {} + + // DATACMNS-1366 + + @RequiredArgsConstructor + static class PropertyPopulationRequired { + + private final String firstname, lastname; + private String email; + } + + @RequiredArgsConstructor + static class PropertyPopulationNotRequired { + + private final String firstname, lastname; + } + + @RequiredArgsConstructor + static class PropertyPopulationNotRequiredWithTransient { + + private final String firstname, lastname; + private @Transient String email; + } }