diff --git a/src/main/java/org/springframework/data/mapping/context/AbstractMappingContext.java b/src/main/java/org/springframework/data/mapping/context/AbstractMappingContext.java index 4c2ecc88f..1fbc89791 100644 --- a/src/main/java/org/springframework/data/mapping/context/AbstractMappingContext.java +++ b/src/main/java/org/springframework/data/mapping/context/AbstractMappingContext.java @@ -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> initialEntitySet) { setManagedTypes(ManagedTypes.fromIterable(initialEntitySet)); @@ -415,17 +415,19 @@ public abstract class AbstractMappingContext descriptors = new HashMap<>(); + if (shouldCreateProperties(userTypeInformation)) { + PropertyDescriptor[] pds = BeanUtils.getPropertyDescriptors(type); + Map 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 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 { + + String name; + + @Override + public Iterator iterator() { + return Collections.emptyIterator(); + } + } + + static class MyStreamable implements Streamable { + + String name; + + @Override + public Iterator iterator() { + return Collections.emptyIterator(); + } + } + + record StreamComponent(String name) { + + } + }