DATAJPA-658 - Polishing.
Moved identifier attribute detection into JpaMetamodel and refactored to Java 8 Stream based lookup. The identifier property calculation is now contained in a Lazy instance so that repeated calls reuse the same outcome. Original pull request: #146.
This commit is contained in:
@@ -35,9 +35,7 @@ import javax.persistence.OneToOne;
|
||||
import javax.persistence.OrderColumn;
|
||||
import javax.persistence.Transient;
|
||||
import javax.persistence.Version;
|
||||
import javax.persistence.metamodel.EntityType;
|
||||
import javax.persistence.metamodel.Metamodel;
|
||||
import javax.persistence.metamodel.SingularAttribute;
|
||||
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.data.annotation.AccessType.Type;
|
||||
@@ -48,6 +46,7 @@ import org.springframework.data.mapping.model.AnnotationBasedPersistentProperty;
|
||||
import org.springframework.data.mapping.model.Property;
|
||||
import org.springframework.data.mapping.model.SimpleTypeHolder;
|
||||
import org.springframework.data.util.ClassTypeInformation;
|
||||
import org.springframework.data.util.Lazy;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -97,7 +96,8 @@ class JpaPersistentPropertyImpl extends AnnotationBasedPersistentProperty<JpaPer
|
||||
private final @Nullable TypeInformation<?> associationTargetType;
|
||||
private final boolean updateable;
|
||||
private final JpaMetamodel metamodel;
|
||||
private final EntityType<?> entityType;
|
||||
|
||||
private final Lazy<Boolean> isIdProperty;
|
||||
|
||||
/**
|
||||
* Creates a new {@link JpaPersistentPropertyImpl}
|
||||
@@ -114,33 +114,13 @@ class JpaPersistentPropertyImpl extends AnnotationBasedPersistentProperty<JpaPer
|
||||
|
||||
Assert.notNull(metamodel, "Metamodel must not be null!");
|
||||
|
||||
this.entityType = tryResolveEntityType(metamodel, getOwner().getType());
|
||||
this.usePropertyAccess = detectPropertyAccess();
|
||||
this.associationTargetType = detectAssociationTargetType();
|
||||
this.updateable = detectUpdatability();
|
||||
this.metamodel = new JpaMetamodel(metamodel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the {@link EntityType} for the given Entity {@link Class} or null if given {@code type} is not a mapped
|
||||
* entity.
|
||||
*
|
||||
* @param metamodel
|
||||
* @param type
|
||||
* @return
|
||||
*/
|
||||
private EntityType<?> tryResolveEntityType(Metamodel metamodel, Class<?> type) {
|
||||
|
||||
EntityType<?> ownerEntityType = null;
|
||||
|
||||
for (EntityType<?> entityType : metamodel.getEntities()) {
|
||||
if (entityType.getJavaType().equals(type)) {
|
||||
ownerEntityType = entityType;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ownerEntityType;
|
||||
this.isIdProperty = Lazy.of(() -> ID_ANNOTATIONS.stream().anyMatch(it -> isAnnotationPresent(it)) //
|
||||
|| this.metamodel.isSingleIdAttribute(getOwner().getType(), getName(), getType()));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -168,27 +148,7 @@ class JpaPersistentPropertyImpl extends AnnotationBasedPersistentProperty<JpaPer
|
||||
*/
|
||||
@Override
|
||||
public boolean isIdProperty() {
|
||||
|
||||
boolean isId ID_ANNOTATIONS.stream().anyMatch(it -> isAnnotationPresent(it));
|
||||
|
||||
if (isId) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (isIdPropertyCandidateAccordingToMetaModel()) {
|
||||
|
||||
SingularAttribute<?, ?> idAttribute = entityType.getId(getType());
|
||||
if (idAttribute.getName().equals(getName())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isIdPropertyCandidateAccordingToMetaModel() {
|
||||
return entityType != null && entityType.hasSingleIdAttribute()
|
||||
&& entityType.getIdType().getJavaType().equals(getType());
|
||||
return isIdProperty.get();
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -21,8 +21,10 @@ import java.util.HashSet;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.persistence.metamodel.EntityType;
|
||||
import javax.persistence.metamodel.ManagedType;
|
||||
import javax.persistence.metamodel.Metamodel;
|
||||
import javax.persistence.metamodel.SingularAttribute;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@@ -63,6 +65,25 @@ public class JpaMetamodel {
|
||||
return getManagedTypes().contains(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the attribute of given name and type is the single identifier attribute of the given entity.
|
||||
*
|
||||
* @param entity must not be {@literal null}.
|
||||
* @param name must not be {@literal null}.
|
||||
* @param attributeType must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
public boolean isSingleIdAttribute(Class<?> entity, String name, Class<?> attributeType) {
|
||||
|
||||
return metamodel.getEntities().stream() //
|
||||
.filter(it -> it.getJavaType().equals(entity)) //
|
||||
.findFirst() //
|
||||
.flatMap(it -> getSingularIdAttribute(it)) //
|
||||
.filter(it -> it.getJavaType().equals(attributeType)) //
|
||||
.map(it -> it.getName().equals(name)) //
|
||||
.orElse(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all types managed by the backing {@link Metamodel}. Skips {@link ManagedType} instances that return
|
||||
* {@literal null} for calls to {@link ManagedType#getJavaType()}.
|
||||
@@ -91,4 +112,22 @@ public class JpaMetamodel {
|
||||
|
||||
return this.managedTypes.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link SingularAttribute} representing the identifier of the given {@link EntityType} if it contains a
|
||||
* singular one.
|
||||
*
|
||||
* @param entityType must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
private static Optional<? extends SingularAttribute<?, ?>> getSingularIdAttribute(EntityType<?> entityType) {
|
||||
|
||||
if (!entityType.hasSingleIdAttribute()) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
return entityType.getSingularAttributes().stream() //
|
||||
.filter(SingularAttribute::isId) //
|
||||
.findFirst();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user