DATAMONGO-505 - Fixed handling of parameter binding of associations and collection values.
Instead of converting given association values as-is, ConvertingParameterAccessor now converts each collection value into a DBRef individually.
This commit is contained in:
@@ -15,7 +15,11 @@
|
||||
*/
|
||||
package org.springframework.data.mongodb.repository.query;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
@@ -25,6 +29,9 @@ import org.springframework.data.mongodb.core.geo.Point;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
|
||||
import org.springframework.data.repository.query.ParameterAccessor;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import com.mongodb.DBRef;
|
||||
|
||||
/**
|
||||
* Custom {@link ParameterAccessor} that uses a {@link MongoWriter} to serialize parameters into Mongo format.
|
||||
@@ -158,7 +165,28 @@ public class ConvertingParameterAccessor implements MongoParameterAccessor {
|
||||
* @see org.springframework.data.mongodb.repository.ConvertingParameterAccessor.PotentiallConvertingIterator#nextConverted()
|
||||
*/
|
||||
public Object nextConverted(MongoPersistentProperty property) {
|
||||
return property.isAssociation() ? writer.toDBRef(next(), property) : getConvertedValue(next());
|
||||
|
||||
Object next = next();
|
||||
|
||||
if (next == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (property.isAssociation()) {
|
||||
if (next.getClass().isArray() || next instanceof Iterable) {
|
||||
|
||||
List<DBRef> dbRefs = new ArrayList<DBRef>();
|
||||
for (Object element : asCollection(next)) {
|
||||
dbRefs.add(writer.toDBRef(element, property));
|
||||
}
|
||||
|
||||
return dbRefs;
|
||||
} else {
|
||||
return writer.toDBRef(next, property);
|
||||
}
|
||||
}
|
||||
|
||||
return getConvertedValue(next);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -170,6 +198,33 @@ public class ConvertingParameterAccessor implements MongoParameterAccessor {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the given object as {@link Collection}. Will do a copy of it if it implements {@link Iterable} or is an
|
||||
* array. Will return an empty {@link Collection} in case {@literal null} is given. Will wrap all other types into a
|
||||
* single-element collction
|
||||
*
|
||||
* @param source
|
||||
* @return
|
||||
*/
|
||||
private static Collection<?> asCollection(Object source) {
|
||||
|
||||
if (source instanceof Iterable) {
|
||||
|
||||
List<Object> result = new ArrayList<Object>();
|
||||
for (Object element : (Iterable<?>) source) {
|
||||
result.add(element);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
if (source == null) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
return source.getClass().isArray() ? CollectionUtils.arrayToList(source) : Collections.singleton(source);
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom {@link Iterator} that adds a method to access elements in a converted manner.
|
||||
*
|
||||
|
||||
@@ -15,11 +15,13 @@
|
||||
*/
|
||||
package org.springframework.data.mongodb.repository.query;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@@ -27,7 +29,11 @@ import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.data.mongodb.MongoDbFactory;
|
||||
import org.springframework.data.mongodb.core.convert.MappingMongoConverter;
|
||||
import org.springframework.data.mongodb.core.mapping.DBRef;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
|
||||
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
|
||||
import org.springframework.data.mongodb.repository.query.ConvertingParameterAccessor.PotentiallyConvertingIterator;
|
||||
|
||||
import com.mongodb.BasicDBList;
|
||||
|
||||
@@ -76,4 +82,66 @@ public class ConvertingParameterAccessorUnitTests {
|
||||
|
||||
assertThat(result, is((Object) reference));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-505
|
||||
*/
|
||||
@Test
|
||||
public void convertsAssociationsToDBRef() {
|
||||
|
||||
Property property = new Property();
|
||||
property.id = 5L;
|
||||
|
||||
Object result = setupAndConvert(property);
|
||||
|
||||
assertThat(result, is(instanceOf(com.mongodb.DBRef.class)));
|
||||
com.mongodb.DBRef dbRef = (com.mongodb.DBRef) result;
|
||||
assertThat(dbRef.getRef(), is("property"));
|
||||
assertThat(dbRef.getId(), is((Object) 5L));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-505
|
||||
*/
|
||||
@Test
|
||||
public void convertsAssociationsToDBRefForCollections() {
|
||||
|
||||
Property property = new Property();
|
||||
property.id = 5L;
|
||||
|
||||
Object result = setupAndConvert(Arrays.asList(property));
|
||||
|
||||
assertThat(result, is(instanceOf(Collection.class)));
|
||||
Collection<?> collection = (Collection<?>) result;
|
||||
|
||||
assertThat(collection, hasSize(1));
|
||||
Object element = collection.iterator().next();
|
||||
|
||||
assertThat(element, is(instanceOf(com.mongodb.DBRef.class)));
|
||||
com.mongodb.DBRef dbRef = (com.mongodb.DBRef) element;
|
||||
assertThat(dbRef.getRef(), is("property"));
|
||||
assertThat(dbRef.getId(), is((Object) 5L));
|
||||
}
|
||||
|
||||
private Object setupAndConvert(Object... parameters) {
|
||||
|
||||
MongoParameterAccessor delegate = new StubParameterAccessor(parameters);
|
||||
PotentiallyConvertingIterator iterator = new ConvertingParameterAccessor(converter, delegate).iterator();
|
||||
|
||||
MongoPersistentEntity<?> entity = context.getPersistentEntity(Entity.class);
|
||||
MongoPersistentProperty property = entity.getPersistentProperty("property");
|
||||
|
||||
return iterator.nextConverted(property);
|
||||
}
|
||||
|
||||
static class Entity {
|
||||
|
||||
@DBRef
|
||||
Property property;
|
||||
}
|
||||
|
||||
static class Property {
|
||||
|
||||
Long id;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user