Do not create persistent properties for Map and Collection-like entities.

These types are expected to behave like maps and collections and should not carry properties.
The only exception are types implementing Streamable as Streamable can be used in domain types.

Resolves: #3056
Original Pull Request: #3059
This commit is contained in:
Mark Paluch
2024-03-07 09:32:56 +01:00
committed by Christoph Strobl
parent 8dbfb9a6ab
commit 3db2669512
2 changed files with 81 additions and 17 deletions

View File

@@ -59,6 +59,7 @@ import org.springframework.data.mapping.model.Property;
import org.springframework.data.mapping.model.SimpleTypeHolder;
import org.springframework.data.spel.EvaluationContextProvider;
import org.springframework.data.spel.ExtensionAwareEvaluationContextProvider;
import org.springframework.data.util.CustomCollections;
import org.springframework.data.util.KotlinReflectionUtils;
import org.springframework.data.util.NullableWrapperConverters;
import org.springframework.data.util.Optionals;
@@ -143,7 +144,6 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
*
* @param initialEntitySet
* @see #setManagedTypes(ManagedTypes)
*
*/
public void setInitialEntitySet(Set<? extends Class<?>> initialEntitySet) {
setManagedTypes(ManagedTypes.fromIterable(initialEntitySet));
@@ -415,17 +415,19 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
persistentEntities.put(typeInformation, Optional.of(entity));
}
PropertyDescriptor[] pds = BeanUtils.getPropertyDescriptors(type);
Map<String, PropertyDescriptor> descriptors = new HashMap<>();
if (shouldCreateProperties(userTypeInformation)) {
PropertyDescriptor[] pds = BeanUtils.getPropertyDescriptors(type);
Map<String, PropertyDescriptor> descriptors = new HashMap<>();
for (PropertyDescriptor descriptor : pds) {
descriptors.put(descriptor.getName(), descriptor);
for (PropertyDescriptor descriptor : pds) {
descriptors.put(descriptor.getName(), descriptor);
}
PersistentPropertyCreator persistentPropertyCreator = new PersistentPropertyCreator(entity, descriptors);
ReflectionUtils.doWithFields(type, persistentPropertyCreator, PersistentPropertyFilter.INSTANCE);
persistentPropertyCreator.addPropertiesForRemainingDescriptors();
}
PersistentPropertyCreator persistentPropertyCreator = new PersistentPropertyCreator(entity, descriptors);
ReflectionUtils.doWithFields(type, persistentPropertyCreator, PersistentPropertyFilter.INSTANCE);
persistentPropertyCreator.addPropertiesForRemainingDescriptors();
entity.verify();
if (persistentPropertyAccessorFactory.isSupported(entity)) {
@@ -475,6 +477,35 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
*/
protected abstract P createPersistentProperty(Property property, E owner, SimpleTypeHolder simpleTypeHolder);
/**
* Whether to create the {@link PersistentProperty}s for the given {@link TypeInformation}.
*
* @param typeInformation must not be {@literal null}.
* @return {@literal true} properties should be created, {@literal false} otherwise
*/
protected boolean shouldCreateProperties(TypeInformation<?> typeInformation) {
Class<?> type = typeInformation.getType();
return !typeInformation.isMap() && !isCollectionLike(type);
}
/**
* In contrast to TypeInformation, we do not consider types implementing Streamable collection-like as domain types
* can implement that type.
*
* @param type must not be {@literal null}.
* @return
* @see TypeInformation#isCollectionLike()
*/
private static boolean isCollectionLike(Class<?> type) {
return type.isArray() //
|| Iterable.class.equals(type) //
|| Streamable.class.equals(type) //
|| Collection.class.isAssignableFrom(type) || CustomCollections.isCollection(type);
}
@Override
public void afterPropertiesSet() {
initialize();
@@ -532,6 +563,7 @@ public abstract class AbstractMappingContext<E extends MutablePersistentEntity<?
this.remainingDescriptors = remainingDescriptors;
}
@Override
public void doWith(Field field) {
String fieldName = field.getName();