, P extends PersistentProperty> {
- private static final Predicate>> IS_ENTITY = PersistentProperty::isEntity;
-
private final ConcurrentLruCache propertyPaths = new ConcurrentLruCache<>(512, it -> createPersistentPropertyPath(it.path(), it.type()));
private final MappingContext context;
@@ -228,7 +234,18 @@ private Collection> from(TypeInformation type,
return Collections.emptyList();
}
- return from(context.getRequiredPersistentEntity(actualType), filter, traversalGuard, basePath);
+ E entity;
+ if (type.isCollectionLike() || type.isMap()) {
+ entity = context.getPersistentEntity(actualType);
+ } else {
+ entity = context.getRequiredPersistentEntity(actualType);
+ }
+
+ if (entity == null) {
+ return Collections.emptyList();
+ }
+
+ return from(entity, filter, traversalGuard, basePath);
}
private Collection> from(E entity, Predicate super P> filter, Predicate traversalGuard,
@@ -251,9 +268,11 @@ private Collection> from(E entity, Predicate super P
properties.add(currentPath);
}
- if (traversalGuard.and(IS_ENTITY).test(persistentProperty)) {
- var persistentEntity = context.getRequiredPersistentEntity(persistentProperty);
- properties.addAll(from(persistentEntity, filter, traversalGuard, currentPath));
+ if (traversalGuard.test(persistentProperty)) {
+ E persistentEntity = context.getPersistentEntity(persistentProperty);
+ if (persistentEntity != null) {
+ properties.addAll(from(persistentEntity, filter, traversalGuard, currentPath));
+ }
}
};
diff --git a/src/test/java/org/springframework/data/auditing/MappingAuditableBeanWrapperFactoryUnitTests.java b/src/test/java/org/springframework/data/auditing/MappingAuditableBeanWrapperFactoryUnitTests.java
index bf3b6fdeb5..1dd7edf358 100755
--- a/src/test/java/org/springframework/data/auditing/MappingAuditableBeanWrapperFactoryUnitTests.java
+++ b/src/test/java/org/springframework/data/auditing/MappingAuditableBeanWrapperFactoryUnitTests.java
@@ -84,6 +84,18 @@ void cacheWarmedWithKnownPersistentEntities() {
assertThat(metadataCache).hasSize(4);
}
+ @Test // GH-3515
+ void initializesFactoryForEntityWithNestedMapProperty() {
+
+ var context = new SampleMappingContext();
+ context.getPersistentEntity(WithNestedMap.class);
+ context.findPersistentPropertyPaths(WithNestedMap.class, it -> true);
+
+ var factory = new MappingAuditableBeanWrapperFactory(PersistentEntities.of(context));
+
+ assertThat(factory.getBeanWrapperFor(new WithNestedMap())).isNotNull();
+ }
+
@Test // DATACMNS-365
void discoversAuditingPropertyOnField() {
@@ -406,4 +418,12 @@ static class WithEmbedded {
Collection embeddeds;
Map embeddedMap;
}
+
+ static class Cell {
+ Object value;
+ }
+
+ static class WithNestedMap {
+ Map> values;
+ }
}
diff --git a/src/test/java/org/springframework/data/mapping/context/PersistentPropertyPathFactoryUnitTests.java b/src/test/java/org/springframework/data/mapping/context/PersistentPropertyPathFactoryUnitTests.java
index eb56b73efe..24dc829389 100644
--- a/src/test/java/org/springframework/data/mapping/context/PersistentPropertyPathFactoryUnitTests.java
+++ b/src/test/java/org/springframework/data/mapping/context/PersistentPropertyPathFactoryUnitTests.java
@@ -41,6 +41,7 @@
*
* @author Oliver Gierke
* @author Christoph Strobl
+ * @author Mark Paluch
* @soundtrack Cypress Hill - Illusions (Q-Tip Remix, Unreleased & Revamped)
*/
class PersistentPropertyPathFactoryUnitTests {
@@ -176,6 +177,22 @@ void returnsShortestPathFirst() {
.hasValueSatisfying(it -> assertThat(it.toDotPath()).isEqualTo("third.lastname"));
}
+ @Test // GH-3515
+ void returnsPathsForMapWithEntityKeyAndSimpleValueType() {
+
+ var paths = factory.from(WithEntityKeyMap.class, it -> true);
+
+ assertThat(paths).extracting(PersistentPropertyPath::toDotPath).containsExactly("map");
+ }
+
+ @Test // GH-3515
+ void returnsPathsForRawTypeComplexBound() {
+
+ var paths = factory.from(BoundedGeneric.class, it -> true);
+
+ assertThat(paths).extracting(PersistentPropertyPath::toDotPath).containsExactly("map");
+ }
+
static class PersonSample {
List persons;
}
@@ -222,4 +239,13 @@ static class Second {
static class Third {
String lastname;
}
+
+ static class WithEntityKeyMap {
+ Map map;
+ }
+
+ static class BoundedGeneric {
+ Map map;
+ }
+
}