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 f5d739bad..8c628799b 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 @@ -60,6 +60,7 @@ import com.mongodb.client.MongoCollection; * * @author Christoph Strobl * @author Mark Paluch + * @author Stefan Bildl * @since 3.3 */ public final class ReferenceLookupDelegate { @@ -106,6 +107,11 @@ public final class ReferenceLookupDelegate { Object value = source instanceof DocumentReferenceSource documentReferenceSource ? documentReferenceSource.getTargetSource() : source; + // GH-4612 no need to query database if target collection is empty + if (value != null && property.isCollectionLike() && (value instanceof Collection c) && c.isEmpty()) { + return new ArrayList<>(); + } + DocumentReferenceQuery filter = computeFilter(property, source, spELContext); ReferenceCollection referenceCollection = computeReferenceContext(property, value, spELContext); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/ReferenceLookupDelegateUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/ReferenceLookupDelegateUnitTests.java index 3b2e8e69b..fd24a7e5c 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/ReferenceLookupDelegateUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/ReferenceLookupDelegateUnitTests.java @@ -15,17 +15,11 @@ */ package org.springframework.data.mongodb.core.convert; -import static org.assertj.core.api.Assertions.*; -import static org.mockito.Mockito.*; - -import java.util.Collections; - import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; - import org.springframework.data.mapping.context.MappingContext; import org.springframework.data.mapping.model.SpELContext; import org.springframework.data.mongodb.core.convert.ReferenceResolver.MongoEntityReader; @@ -33,7 +27,11 @@ import org.springframework.data.mongodb.core.mapping.DocumentReference; import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity; import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty; import org.springframework.expression.EvaluationContext; -import org.springframework.expression.spel.standard.SpelExpressionParser; + +import java.util.Collections; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.*; /** * Unit tests for {@link ReferenceLookupDelegate}. @@ -52,9 +50,17 @@ class ReferenceLookupDelegateUnitTests { @BeforeEach void beforeEach() { - lookupDelegate = new ReferenceLookupDelegate(mappingContext, spELContext); - when(spELContext.getParser()).thenReturn(new SpelExpressionParser()); + } + + @Test // GH-4612 + void shouldResolveEmptyListOnEmptyTargetCollection() { + MongoPersistentProperty property = mock(MongoPersistentProperty.class); + ReferenceLookupDelegate.LookupFunction lookupFunction = mock(ReferenceLookupDelegate.LookupFunction.class); + + when(property.isCollectionLike()).thenReturn(true); + lookupDelegate.readReference(property, Collections.emptyList(), lookupFunction, entityReader); + verify(lookupFunction, never()).apply(any(), any()); } @Test // GH-3842