From 4e960a968288833f6e8ca6a8ce429eef226972a4 Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Wed, 8 Sep 2021 09:24:15 +0200 Subject: [PATCH] Fix document reference on empty reference arrays. This commit fixes an issue caused by empty reference arrays. Closes #3805 Original pull request: #3807. --- .../core/convert/ReferenceLookupDelegate.java | 9 ++++- .../MongoTemplateDocumentReferenceTests.java | 39 +++++++++++++++++++ 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceLookupDelegate.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceLookupDelegate.java index 36ccc23a6..a2726e633 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceLookupDelegate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/ReferenceLookupDelegate.java @@ -19,6 +19,7 @@ import java.lang.annotation.Annotation; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -122,7 +123,9 @@ public final class ReferenceLookupDelegate { // Use the first value as a reference for others in case of collection like if (value instanceof Iterable) { - value = ((Iterable) value).iterator().next(); + + Iterator iterator = ((Iterable) value).iterator(); + value = iterator.hasNext() ? iterator.next() : new Document(); } // handle DBRef value @@ -266,6 +269,10 @@ public final class ReferenceLookupDelegate { ors.add(decoded); } + if(ors.isEmpty()) { + return new ListDocumentReferenceQuery(new Document("_id", new Document("$exists", false)), sort); + } + return new ListDocumentReferenceQuery(new Document("$or", ors), sort); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateDocumentReferenceTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateDocumentReferenceTests.java index 06d288d1f..2b96b3dc2 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateDocumentReferenceTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateDocumentReferenceTests.java @@ -25,6 +25,7 @@ import lombok.Getter; import lombok.Setter; import lombok.ToString; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.LinkedHashMap; @@ -679,6 +680,41 @@ public class MongoTemplateDocumentReferenceTests { assertThat(result.getSimpleValueRef()).containsExactly(new SimpleObjectRef("ref-2", "me-the-2-referenced-object")); } + @Test // GH-3805 + void loadEmptyCollectionReference() { + + String rootCollectionName = template.getCollectionName(CollectionRefRoot.class); + + // an empty reference array. + Document source = new Document("_id", "id-1").append("value", "v1").append("simplePreinitializedValueRef", + Collections.emptyList()); + + template.execute(db -> { + db.getCollection(rootCollectionName).insertOne(source); + return null; + }); + + CollectionRefRoot result = template.findOne(query(where("id").is("id-1")), CollectionRefRoot.class); + assertThat(result.simplePreinitializedValueRef).isEmpty(); + } + + @Test // GH-3805 + void loadNoExistingCollectionReference() { + + String rootCollectionName = template.getCollectionName(CollectionRefRoot.class); + + // no reference array at all + Document source = new Document("_id", "id-1").append("value", "v1"); + + template.execute(db -> { + db.getCollection(rootCollectionName).insertOne(source); + return null; + }); + + CollectionRefRoot result = template.findOne(query(where("id").is("id-1")), CollectionRefRoot.class); + assertThat(result.simplePreinitializedValueRef).isEmpty(); + } + @Test // GH-3602 void queryForReference() { @@ -1122,6 +1158,9 @@ public class MongoTemplateDocumentReferenceTests { @DocumentReference(lookup = "{ '_id' : '?#{#target}' }") // List simpleValueRef; + @DocumentReference + List simplePreinitializedValueRef = new ArrayList<>(); + @DocumentReference(lookup = "{ '_id' : '?#{#target}' }", sort = "{ '_id' : -1 } ") // List simpleSortedValueRef;