diff --git a/src/main/java/org/springframework/data/mapping/PersistentEntity.java b/src/main/java/org/springframework/data/mapping/PersistentEntity.java index 34e58cbc7..64fa4971b 100644 --- a/src/main/java/org/springframework/data/mapping/PersistentEntity.java +++ b/src/main/java/org/springframework/data/mapping/PersistentEntity.java @@ -82,6 +82,12 @@ public interface PersistentEntity> { */ Optional

getIdProperty(); + default P getRequiredIdProperty() { + + return getIdProperty().orElseThrow( + () -> new IllegalStateException(String.format("Required identifier property not found for %s!", getType()))); + } + /** * Returns the version property of the {@link PersistentEntity}. Can be {@literal null} in case no version property is * available on the entity. @@ -94,11 +100,22 @@ public interface PersistentEntity> { * Obtains a {@link PersistentProperty} instance by name. * * @param name The name of the property - * @return the {@link PersistentProperty} or {@literal null} if it doesn't exist. + * @return the {@link PersistentProperty} or {@literal Optional#empty()} if it doesn't exist. */ Optional

getPersistentProperty(String name); - P getRequiredPersistentProperty(String name); + /** + * Returns the {@link PersistentProperty} with the given name. + * + * @param name the name of the property, must not be {@literal null} or empty. + * @return the {@link PersistentProperty} with the given name. + * @throws IllegalArgumentException in case no property with the given name exists. + */ + default P getRequiredPersistentProperty(String name) { + + return getPersistentProperty(name).orElseThrow( + () -> new IllegalArgumentException(String.format("No property %s found for type %s!", name, getType()))); + } /** * Returns the property equipped with an annotation of the given type. diff --git a/src/main/java/org/springframework/data/mapping/PersistentProperty.java b/src/main/java/org/springframework/data/mapping/PersistentProperty.java index 666854baa..68e9afcad 100644 --- a/src/main/java/org/springframework/data/mapping/PersistentProperty.java +++ b/src/main/java/org/springframework/data/mapping/PersistentProperty.java @@ -91,6 +91,10 @@ public interface PersistentProperty

> { Optional> getAssociation(); + default Association

getRequiredAssociation() { + return getAssociation().orElseThrow(() -> new IllegalStateException("No association found!")); + } + /** * Returns whether the type of the {@link PersistentProperty} is actually to be regarded as {@link PersistentEntity} * in turn. diff --git a/src/main/java/org/springframework/data/mapping/context/PersistentEntities.java b/src/main/java/org/springframework/data/mapping/context/PersistentEntities.java index 747a74635..395b9ca10 100644 --- a/src/main/java/org/springframework/data/mapping/context/PersistentEntities.java +++ b/src/main/java/org/springframework/data/mapping/context/PersistentEntities.java @@ -20,6 +20,7 @@ import java.util.Optional; import java.util.stream.Collectors; import org.springframework.data.mapping.PersistentEntity; +import org.springframework.data.mapping.PersistentProperty; import org.springframework.data.util.Streamable; import org.springframework.data.util.TypeInformation; import org.springframework.util.Assert; @@ -30,7 +31,7 @@ import org.springframework.util.Assert; * @author Oliver Gierke * @since 1.8 */ -public class PersistentEntities implements Streamable> { +public class PersistentEntities implements Streamable>> { private final Streamable> contexts; @@ -53,7 +54,7 @@ public class PersistentEntities implements Streamable> { * @param type can be {@literal null}. * @return */ - public Optional> getPersistentEntity(Class type) { + public Optional>> getPersistentEntity(Class type) { return contexts.stream()// .filter(it -> it.hasPersistentEntityFor(type))// @@ -69,7 +70,7 @@ public class PersistentEntities implements Streamable> { * @return the {@link PersistentEntity} for the given domain type. * @throws IllegalArgumentException in case no {@link PersistentEntity} can be found for the given type. */ - public PersistentEntity getRequiredPersistentEntity(Class type) { + public PersistentEntity> getRequiredPersistentEntity(Class type) { Assert.notNull(type, "Domain type must not be null!"); @@ -94,9 +95,10 @@ public class PersistentEntities implements Streamable> { * @see java.lang.Iterable#iterator() */ @Override - public Iterator> iterator() { + public Iterator>> iterator() { - return contexts.stream().> flatMap(it -> it.getPersistentEntities().stream()) + return contexts.stream() + .>> flatMap(it -> it.getPersistentEntities().stream()) .collect(Collectors.toList()).iterator(); } } diff --git a/src/main/java/org/springframework/data/mapping/model/AbstractPersistentProperty.java b/src/main/java/org/springframework/data/mapping/model/AbstractPersistentProperty.java index e411d1d56..f1a9588b4 100644 --- a/src/main/java/org/springframework/data/mapping/model/AbstractPersistentProperty.java +++ b/src/main/java/org/springframework/data/mapping/model/AbstractPersistentProperty.java @@ -56,8 +56,9 @@ public abstract class AbstractPersistentProperty

protected final Optional> association; private final @Getter PersistentEntity owner; private final @Getter(AccessLevel.PROTECTED) Property property; - private final SimpleTypeHolder simpleTypeHolder; private final Lazy hashCode; + private final Lazy usePropertyAccess; + private final Lazy>> entityTypeInformation; public AbstractPersistentProperty(Property property, PersistentEntity owner, SimpleTypeHolder simpleTypeHolder) { @@ -67,12 +68,19 @@ public abstract class AbstractPersistentProperty

this.name = property.getName(); this.rawType = property.getType(); - this.information = PropertyPath.from(Pattern.quote(property.getName()), owner.getTypeInformation()).getTypeInformation(); + this.information = PropertyPath.from(Pattern.quote(property.getName()), owner.getTypeInformation()) + .getTypeInformation(); this.property = property; this.association = isAssociation() ? Optional.of(createAssociation()) : Optional.empty(); this.owner = owner; - this.simpleTypeHolder = simpleTypeHolder; + this.hashCode = Lazy.of(property::hashCode); + this.usePropertyAccess = Lazy + .of(() -> owner.getType().isInterface() || getField().map(it -> it.equals(CAUSE_FIELD)).orElse(false)); + this.entityTypeInformation = Lazy.of(() -> Optional.ofNullable(information.getActualType())// + .filter(it -> !simpleTypeHolder.isSimpleType(it.getType()))// + .filter(it -> !it.isCollectionLike())// + .filter(it -> !it.isMap())); } protected abstract Association

createAssociation(); @@ -124,19 +132,9 @@ public abstract class AbstractPersistentProperty

return Collections.emptySet(); } - TypeInformation candidate = getTypeInformationIfEntityCandidate(); - return candidate != null ? Collections.singleton(candidate) : Collections.emptySet(); - } - - private TypeInformation getTypeInformationIfEntityCandidate() { - - TypeInformation candidate = information.getActualType(); - - if (candidate == null || simpleTypeHolder.isSimpleType(candidate.getType())) { - return null; - } - - return candidate.isCollectionLike() || candidate.isMap() ? null : candidate; + return entityTypeInformation.get()// + .map(it -> Collections.singleton(it))// + .orElseGet(() -> Collections.emptySet()); } /* @@ -244,7 +242,7 @@ public abstract class AbstractPersistentProperty

*/ @Override public boolean isEntity() { - return !isTransient() && getTypeInformationIfEntityCandidate() != null; + return !isTransient() && entityTypeInformation.get().isPresent(); } /* @@ -284,7 +282,7 @@ public abstract class AbstractPersistentProperty

* @see org.springframework.data.mongodb.core.mapping.MongoPersistentProperty#usePropertyAccess() */ public boolean usePropertyAccess() { - return owner.getType().isInterface() || getField().map(it -> it.equals(CAUSE_FIELD)).orElse(false); + return usePropertyAccess.get(); } /* diff --git a/src/main/java/org/springframework/data/mapping/model/AnnotationBasedPersistentProperty.java b/src/main/java/org/springframework/data/mapping/model/AnnotationBasedPersistentProperty.java index 9a337934a..66a9c0001 100644 --- a/src/main/java/org/springframework/data/mapping/model/AnnotationBasedPersistentProperty.java +++ b/src/main/java/org/springframework/data/mapping/model/AnnotationBasedPersistentProperty.java @@ -37,6 +37,7 @@ import org.springframework.data.annotation.Version; import org.springframework.data.mapping.Association; import org.springframework.data.mapping.PersistentEntity; import org.springframework.data.mapping.PersistentProperty; +import org.springframework.data.util.Lazy; import org.springframework.data.util.Optionals; import org.springframework.util.Assert; @@ -55,8 +56,8 @@ public abstract class AnnotationBasedPersistentProperty

value; private final Map, Optional> annotationCache = new HashMap<>(); - private Boolean isTransient; - private boolean usePropertyAccess; + private Lazy isTransient; + private Lazy usePropertyAccess; /** * Creates a new {@link AnnotationBasedPersistentProperty}. @@ -71,9 +72,12 @@ public abstract class AnnotationBasedPersistentProperty

Type.PROPERTY.equals(it.value())) - .orElse(false); this.value = findAnnotation(Value.class); + this.usePropertyAccess = Lazy.of(() -> findPropertyOrOwnerAnnotation(AccessType.class)// + .map(it -> Type.PROPERTY.equals(it.value()))// + .orElse(super.usePropertyAccess())); + this.isTransient = Lazy.of(() -> super.isTransient() || isAnnotationPresent(Transient.class) + || isAnnotationPresent(Value.class) || isAnnotationPresent(Autowired.class)); } /** @@ -152,20 +156,13 @@ public abstract class AnnotationBasedPersistentProperty

Optionals.toStream(it)) // + .map(Object::toString) // .collect(Collectors.joining(" ")); - return builder// -// -// - + super.toString(); + return builder + super.toString(); } private Stream> getAccessors() { 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 ef167ec91..64a2b5f8b 100644 --- a/src/main/java/org/springframework/data/mapping/model/BasicPersistentEntity.java +++ b/src/main/java/org/springframework/data/mapping/model/BasicPersistentEntity.java @@ -21,7 +21,6 @@ import lombok.RequiredArgsConstructor; import java.io.Serializable; import java.lang.annotation.Annotation; import java.util.ArrayList; -import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; @@ -274,17 +273,6 @@ public class BasicPersistentEntity> implement return Optional.ofNullable(propertyCache.get(name)); } - /* - * (non-Javadoc) - * @see org.springframework.data.mapping.PersistentEntity#getRequiredPersistentProperty(java.lang.String) - */ - @Override - public P getRequiredPersistentProperty(String name) { - - return getPersistentProperty(name).orElseThrow( - () -> new IllegalArgumentException(String.format("No property %s found for type %s!", name, getType()))); - } - /* * (non-Javadoc) * @see org.springframework.data.mapping.PersistentEntity#getPersistentProperty(java.lang.Class) @@ -436,8 +424,8 @@ public class BasicPersistentEntity> implement public PersistentPropertyAccessor getPropertyAccessor(Object bean) { Assert.notNull(bean, "Target bean must not be null!"); - Assert.isTrue(getType().isInstance(bean), () -> - String.format(TYPE_MISMATCH, bean.getClass().getName(), getType().getName())); + Assert.isTrue(getType().isInstance(bean), + () -> String.format(TYPE_MISMATCH, bean.getClass().getName(), getType().getName())); return propertyAccessorFactory.getPropertyAccessor(this, bean); } diff --git a/src/main/java/org/springframework/data/repository/core/support/PersistentEntityInformation.java b/src/main/java/org/springframework/data/repository/core/support/PersistentEntityInformation.java index ad0d7dda0..b8f094ed0 100644 --- a/src/main/java/org/springframework/data/repository/core/support/PersistentEntityInformation.java +++ b/src/main/java/org/springframework/data/repository/core/support/PersistentEntityInformation.java @@ -32,7 +32,7 @@ import org.springframework.data.repository.core.EntityInformation; @SuppressWarnings("unchecked") public class PersistentEntityInformation extends AbstractEntityInformation { - private final PersistentEntity persistentEntity; + private final PersistentEntity> persistentEntity; /** * Creates a new {@link PersistableEntityInformation} for the given {@link PersistentEntity}.