Skip to content

Commit 14fbc11

Browse files
committed
DATACMNS-1366 - Introduce PersistentEntity.requiresPropertyPopulation().
The newly introduced method indicates whether any properties have to be populated to create instances of the entity. This is useful for objects that are completely initialized through their constructors as converters then can avoid iterating over all properties just to find out none of them have to be populated.
1 parent 57d0b32 commit 14fbc11

File tree

3 files changed

+66
-0
lines changed

3 files changed

+66
-0
lines changed

src/main/java/org/springframework/data/mapping/PersistentEntity.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,4 +316,13 @@ default <A extends Annotation> A getRequiredAnnotation(Class<A> annotationType)
316316
* @since 2.1
317317
*/
318318
boolean isImmutable();
319+
320+
/**
321+
* Returns whether the entity needs properties to be populated, i.e. if any property exists that's not initialized by
322+
* the constructor.
323+
*
324+
* @return
325+
* @since 2.1
326+
*/
327+
boolean requiresPropertyPopulation();
319328
}

src/main/java/org/springframework/data/mapping/model/BasicPersistentEntity.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ public class BasicPersistentEntity<T, P extends PersistentProperty<P>> implement
9595
private final Lazy<Alias> typeAlias;
9696
private final Lazy<IsNewStrategy> isNewStrategy;
9797
private final Lazy<Boolean> isImmutable;
98+
private final Lazy<Boolean> requiresPropertyPopulation;
9899

99100
/**
100101
* Creates a new {@link BasicPersistentEntity} from the given {@link TypeInformation}.
@@ -134,6 +135,8 @@ public BasicPersistentEntity(TypeInformation<T> information, @Nullable Comparato
134135
: getFallbackIsNewStrategy());
135136

136137
this.isImmutable = Lazy.of(() -> isAnnotationPresent(Immutable.class));
138+
this.requiresPropertyPopulation = Lazy.of(() -> !isImmutable() && properties.stream() //
139+
.anyMatch(it -> !(isConstructorArgument(it) || it.isTransient())));
137140
}
138141

139142
/*
@@ -508,6 +511,15 @@ public boolean isImmutable() {
508511
return isImmutable.get();
509512
}
510513

514+
/*
515+
* (non-Javadoc)
516+
* @see org.springframework.data.mapping.PersistentEntity#requiresPropertyPopulation()
517+
*/
518+
@Override
519+
public boolean requiresPropertyPopulation() {
520+
return requiresPropertyPopulation.get();
521+
}
522+
511523
/*
512524
* (non-Javadoc)
513525
* @see java.lang.Iterable#iterator()

src/test/java/org/springframework/data/mapping/model/BasicPersistentEntityUnitTests.java

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
import static org.junit.Assume.*;
2020
import static org.mockito.Mockito.*;
2121

22+
import lombok.RequiredArgsConstructor;
23+
2224
import java.lang.annotation.Annotation;
2325
import java.lang.annotation.Retention;
2426
import java.lang.annotation.RetentionPolicy;
@@ -27,6 +29,7 @@
2729
import java.util.List;
2830
import java.util.concurrent.CountDownLatch;
2931
import java.util.concurrent.atomic.AtomicBoolean;
32+
import java.util.stream.Stream;
3033

3134
import org.hamcrest.CoreMatchers;
3235
import org.junit.Rule;
@@ -44,6 +47,7 @@
4447
import org.springframework.data.annotation.Immutable;
4548
import org.springframework.data.annotation.LastModifiedBy;
4649
import org.springframework.data.annotation.Persistent;
50+
import org.springframework.data.annotation.Transient;
4751
import org.springframework.data.annotation.TypeAlias;
4852
import org.springframework.data.domain.Persistable;
4953
import org.springframework.data.mapping.Alias;
@@ -355,6 +359,19 @@ public void detectsImmutableEntity() {
355359
assertThat(createEntity(Entity.class).isImmutable()).isFalse();
356360
}
357361

362+
@Test // DATACMNS-1366
363+
public void exposesPropertyPopulationRequired() {
364+
365+
assertThat(createPopulatedPersistentEntity(PropertyPopulationRequired.class).requiresPropertyPopulation()).isTrue();
366+
}
367+
368+
@Test // DATACMNS-1366
369+
public void exposesPropertyPopulationNotRequired() {
370+
371+
Stream.of(PropertyPopulationNotRequired.class, PropertyPopulationNotRequiredWithTransient.class) //
372+
.forEach(it -> assertThat(createPopulatedPersistentEntity(it).requiresPropertyPopulation()).isFalse());
373+
}
374+
358375
private <S> BasicPersistentEntity<S, T> createEntity(Class<S> type) {
359376
return createEntity(type, null);
360377
}
@@ -363,6 +380,12 @@ private <S> BasicPersistentEntity<S, T> createEntity(Class<S> type, Comparator<T
363380
return new BasicPersistentEntity<>(ClassTypeInformation.from(type), comparator);
364381
}
365382

383+
private static PersistentEntity<Object, ?> createPopulatedPersistentEntity(Class<?> type) {
384+
385+
SampleMappingContext context = new SampleMappingContext();
386+
return context.getRequiredPersistentEntity(type);
387+
}
388+
366389
@TypeAlias("foo")
367390
static class AliasedEntity {
368391

@@ -427,4 +450,26 @@ public boolean isNew() {
427450

428451
@Immutable
429452
static class SomeValue {}
453+
454+
// DATACMNS-1366
455+
456+
@RequiredArgsConstructor
457+
static class PropertyPopulationRequired {
458+
459+
private final String firstname, lastname;
460+
private String email;
461+
}
462+
463+
@RequiredArgsConstructor
464+
static class PropertyPopulationNotRequired {
465+
466+
private final String firstname, lastname;
467+
}
468+
469+
@RequiredArgsConstructor
470+
static class PropertyPopulationNotRequiredWithTransient {
471+
472+
private final String firstname, lastname;
473+
private @Transient String email;
474+
}
430475
}

0 commit comments

Comments
 (0)