Skip to content

Commit bd7fe5b

Browse files
committed
DATAMONGO-600 - Fixed parameter binding for derived queries on properties using polymorphism.
We need to retain the type in the serialized DBObject in case a derived query binds parameters for properties that use polymorphism as we serialize the object as nested document and this only matches in an all-or-nothing way. So if the type information is missing, we won't see any results. So we now hand the TypeInformation of the property into the conversion logic and transparently skip the type information removal in case the types differ.
1 parent a237999 commit bd7fe5b

File tree

11 files changed

+136
-28
lines changed

11 files changed

+136
-28
lines changed

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/AbstractMongoConverter.java

+12-5
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,18 @@
11
/*
2-
* Copyright (c) 2011 by the original author(s).
2+
* Copyright 2011-2013 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
66
* You may obtain a copy of the License at
77
*
8-
* http://www.apache.org/licenses/LICENSE-2.0
8+
* http://www.apache.org/licenses/LICENSE-2.0
99
*
1010
* Unless required by applicable law or agreed to in writing, software
1111
* distributed under the License is distributed on an "AS IS" BASIS,
1212
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
*/
16-
1716
package org.springframework.data.mongodb.core.convert;
1817

1918
import java.math.BigInteger;
@@ -33,8 +32,8 @@
3332
* Base class for {@link MongoConverter} implementations. Sets up a {@link GenericConversionService} and populates basic
3433
* converters. Allows registering {@link CustomConversions}.
3534
*
36-
* @author Jon Brisbin <jbrisbin@vmware.com>
37-
* @author Oliver Gierke ogierke@vmware.com
35+
* @author Jon Brisbin
36+
* @author Oliver Gierke
3837
*/
3938
public abstract class AbstractMongoConverter implements MongoConverter, InitializingBean {
4039

@@ -94,6 +93,14 @@ private void initializeConverters() {
9493
conversions.registerConvertersIn(conversionService);
9594
}
9695

96+
/*
97+
* (non-Javadoc)
98+
* @see org.springframework.data.mongodb.core.convert.MongoWriter#convertToMongoType(java.lang.Object)
99+
*/
100+
public Object convertToMongoType(Object obj) {
101+
return convertToMongoType(obj, null);
102+
}
103+
97104
/*
98105
* (non-Javadoc)
99106
* @see org.springframework.data.mongodb.core.core.convert.MongoConverter#getConversionService()

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MappingMongoConverter.java

+12-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2011-2012 by the original author(s).
2+
* Copyright 2011-2013 by the original author(s).
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -816,8 +816,12 @@ protected <T> List<?> unwrapList(BasicDBList dbList, TypeInformation<T> targetTy
816816
return rootList;
817817
}
818818

819+
/*
820+
* (non-Javadoc)
821+
* @see org.springframework.data.mongodb.core.convert.MongoWriter#convertToMongoType(java.lang.Object, org.springframework.data.util.TypeInformation)
822+
*/
819823
@SuppressWarnings("unchecked")
820-
public Object convertToMongoType(Object obj) {
824+
public Object convertToMongoType(Object obj, TypeInformation<?> typeInformation) {
821825

822826
if (obj == null) {
823827
return null;
@@ -864,7 +868,12 @@ public Object convertToMongoType(Object obj) {
864868

865869
DBObject newDbo = new BasicDBObject();
866870
this.write(obj, newDbo);
867-
return removeTypeInfoRecursively(newDbo);
871+
872+
if (typeInformation == null) {
873+
return removeTypeInfoRecursively(newDbo);
874+
}
875+
876+
return !obj.getClass().equals(typeInformation.getType()) ? newDbo : removeTypeInfoRecursively(newDbo);
868877
}
869878

870879
public BasicDBList maybeConvertList(Iterable<?> source) {

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/MongoWriter.java

+13-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2010-2012 the original author or authors.
2+
* Copyright 2010-2013 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -17,6 +17,7 @@
1717

1818
import org.springframework.data.convert.EntityWriter;
1919
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
20+
import org.springframework.data.util.TypeInformation;
2021

2122
import com.mongodb.DBObject;
2223
import com.mongodb.DBRef;
@@ -35,11 +36,21 @@ public interface MongoWriter<T> extends EntityWriter<T, DBObject> {
3536
* Converts the given object into one Mongo will be able to store natively. If the given object can already be stored
3637
* as is, no conversion will happen.
3738
*
38-
* @param obj
39+
* @param obj can be {@literal null}.
3940
* @return
4041
*/
4142
Object convertToMongoType(Object obj);
4243

44+
/**
45+
* Converts the given object into one Mongo will be able to store natively but retains the type information in case
46+
* the given {@link TypeInformation} differs from the given object type.
47+
*
48+
* @param obj can be {@literal null}.
49+
* @param typeInformation can be {@literal null}.
50+
* @return
51+
*/
52+
Object convertToMongoType(Object obj, TypeInformation<?> typeInformation);
53+
4354
/**
4455
* Creates a {@link DBRef} to refer to the given object.
4556
*

spring-data-mongodb/src/main/java/org/springframework/data/mongodb/repository/query/ConvertingParameterAccessor.java

+14-11
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2011 the original author or authors.
2+
* Copyright 2011-2013 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -28,6 +28,7 @@
2828
import org.springframework.data.mongodb.core.geo.Point;
2929
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
3030
import org.springframework.data.repository.query.ParameterAccessor;
31+
import org.springframework.data.util.TypeInformation;
3132
import org.springframework.util.Assert;
3233
import org.springframework.util.CollectionUtils;
3334

@@ -85,12 +86,12 @@ public Sort getSort() {
8586
return delegate.getSort();
8687
}
8788

88-
/* (non-Javadoc)
89-
* @see org.springframework.data.repository.query.ParameterAccessor#getBindableParameter(int)
90-
*/
89+
/*
90+
* (non-Javadoc)
91+
* @see org.springframework.data.repository.query.ParameterAccessor#getBindableValue(int)
92+
*/
9193
public Object getBindableValue(int index) {
92-
93-
return getConvertedValue(delegate.getBindableValue(index));
94+
return getConvertedValue(delegate.getBindableValue(index), null);
9495
}
9596

9697
/*
@@ -101,7 +102,8 @@ public Distance getMaxDistance() {
101102
return delegate.getMaxDistance();
102103
}
103104

104-
/* (non-Javadoc)
105+
/*
106+
* (non-Javadoc)
105107
* @see org.springframework.data.mongodb.repository.MongoParameterAccessor#getGeoNearLocation()
106108
*/
107109
public Point getGeoNearLocation() {
@@ -111,11 +113,12 @@ public Point getGeoNearLocation() {
111113
/**
112114
* Converts the given value with the underlying {@link MongoWriter}.
113115
*
114-
* @param value
116+
* @param value can be {@literal null}.
117+
* @param typeInformation can be {@literal null}.
115118
* @return
116119
*/
117-
private Object getConvertedValue(Object value) {
118-
return writer.convertToMongoType(value);
120+
private Object getConvertedValue(Object value, TypeInformation<?> typeInformation) {
121+
return writer.convertToMongoType(value, typeInformation == null ? null : typeInformation.getActualType());
119122
}
120123

121124
/*
@@ -186,7 +189,7 @@ public Object nextConverted(MongoPersistentProperty property) {
186189
}
187190
}
188191

189-
return getConvertedValue(next);
192+
return getConvertedValue(next, property.getTypeInformation());
190193
}
191194

192195
/*

spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoOperationsUnitTests.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2011 the original author or authors.
2+
* Copyright 2011-2013 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -34,6 +34,7 @@
3434
import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
3535
import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty;
3636
import org.springframework.data.mongodb.core.query.NearQuery;
37+
import org.springframework.data.util.TypeInformation;
3738

3839
import com.mongodb.BasicDBObject;
3940
import com.mongodb.DBObject;
@@ -78,7 +79,7 @@ public MappingContext<? extends MongoPersistentEntity<?>, MongoPersistentPropert
7879
return null;
7980
}
8081

81-
public Object convertToMongoType(Object obj) {
82+
public Object convertToMongoType(Object obj, TypeInformation<?> typeInformation) {
8283
return null;
8384
}
8485

spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/AbstractPersonRepositoryIntegrationTests.java

+20-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2011-2012 the original author or authors.
2+
* Copyright 2011-2013 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -523,4 +523,23 @@ public void executesAndQueryCorrectly() {
523523
assertThat(result, hasSize(1));
524524
assertThat(result, hasItem(oliver));
525525
}
526+
527+
/**
528+
* @see DATAMONGO-600
529+
*/
530+
@Test
531+
public void readsDocumentsWithNestedPolymorphismCorrectly() {
532+
533+
UsernameAndPassword usernameAndPassword = new UsernameAndPassword();
534+
usernameAndPassword.username = "dave";
535+
usernameAndPassword.password = "btcs";
536+
537+
dave.credentials = usernameAndPassword;
538+
539+
repository.save(dave);
540+
541+
List<Person> result = repository.findByCredentials(usernameAndPassword);
542+
assertThat(result, hasSize(1));
543+
assertThat(result, hasItem(dave));
544+
}
526545
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/*
2+
* Copyright 2013 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.data.mongodb.repository;
17+
18+
/**
19+
*
20+
* @author Oliver Gierke
21+
*/
22+
public interface Credentials {
23+
24+
}

spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/Person.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2010-2011 the original author or authors.
2+
* Copyright 2010-2013 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -54,6 +54,8 @@ public enum Sex {
5454
@DBRef
5555
User creator;
5656

57+
Credentials credentials;
58+
5759
public Person() {
5860

5961
this(null, null);

spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepository.java

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2010-2012 the original author or authors.
2+
* Copyright 2010-2013 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -192,4 +192,10 @@ public interface PersonRepository extends MongoRepository<Person, String>, Query
192192
*/
193193
List<Person> findByLastnameNot(String lastname);
194194

195+
/**
196+
* @see DATAMONGO-600
197+
* @param credentials
198+
* @return
199+
*/
200+
List<Person> findByCredentials(Credentials credentials);
195201
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*
2+
* Copyright 2013 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.data.mongodb.repository;
17+
18+
/**
19+
* @author Oliver Gierke
20+
*/
21+
public class UsernameAndPassword implements Credentials {
22+
23+
String username;
24+
String password;
25+
}

spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/query/MongoQueryCreatorUnitTests.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2011-2012 the original author or authors.
2+
* Copyright 2011-2013 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -49,6 +49,7 @@
4949
import org.springframework.data.repository.Repository;
5050
import org.springframework.data.repository.core.support.DefaultRepositoryMetadata;
5151
import org.springframework.data.repository.query.parser.PartTree;
52+
import org.springframework.data.util.TypeInformation;
5253

5354
/**
5455
* Unit test for {@link MongoQueryCreator}.
@@ -74,7 +75,7 @@ public void setUp() throws SecurityException, NoSuchMethodException {
7475
public Object answer(InvocationOnMock invocation) throws Throwable {
7576
return invocation.getArguments()[0];
7677
}
77-
}).when(converter).convertToMongoType(any());
78+
}).when(converter).convertToMongoType(any(), Mockito.any(TypeInformation.class));
7879
}
7980

8081
@Test

0 commit comments

Comments
 (0)