Browse Source

DATAMONGO-1335 - DBObjectAccessor now writes all nested fields correctly.

Previously, DBObjectAccessor has always reset the in-between values when traversing nested properties. This caused previously written values to be erased if subsequent values are written. We now reuse an already existing BasicDBObject if present.
pull/663/head
Oliver Gierke 10 years ago
parent
commit
284e2f462d
  1. 34
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/DBObjectAccessor.java
  2. 28
      spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DBObjectAccessorUnitTests.java

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

@ -75,9 +75,7 @@ class DBObjectAccessor {
String part = parts.next(); String part = parts.next();
if (parts.hasNext()) { if (parts.hasNext()) {
BasicDBObject nestedDbObject = new BasicDBObject(); dbObject = getOrCreateNestedDbObject(part, dbObject);
dbObject.put(part, nestedDbObject);
dbObject = nestedDbObject;
} else { } else {
dbObject.put(part, value); dbObject.put(part, value);
} }
@ -116,8 +114,14 @@ class DBObjectAccessor {
return result; return result;
} }
/**
* Returns the given source object as map, i.e. {@link BasicDBObject}s and maps as is or {@literal null} otherwise.
*
* @param source can be {@literal null}.
* @return
*/
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private Map<String, Object> getAsMap(Object source) { private static Map<String, Object> getAsMap(Object source) {
if (source instanceof BasicDBObject) { if (source instanceof BasicDBObject) {
return (BasicDBObject) source; return (BasicDBObject) source;
@ -129,4 +133,26 @@ class DBObjectAccessor {
return null; return null;
} }
/**
* Returns the {@link DBObject} which either already exists in the given source under the given key, or creates a new
* nested one, registers it with the source and returns it.
*
* @param key must not be {@literal null} or empty.
* @param source must not be {@literal null}.
* @return
*/
private static DBObject getOrCreateNestedDbObject(String key, DBObject source) {
Object existing = source.get(key);
if (existing instanceof BasicDBObject) {
return (BasicDBObject) existing;
}
DBObject nested = new BasicDBObject();
source.put(key, nested);
return nested;
}
} }

28
spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/DBObjectAccessorUnitTests.java

@ -79,6 +79,28 @@ public class DBObjectAccessorUnitTests {
new DBObjectAccessor(null); new DBObjectAccessor(null);
} }
/**
* @see DATAMONGO-1335
*/
@Test
public void writesAllNestingsCorrectly() {
MongoPersistentEntity<?> entity = context.getPersistentEntity(TypeWithTwoNestings.class);
BasicDBObject target = new BasicDBObject();
DBObjectAccessor accessor = new DBObjectAccessor(target);
accessor.put(entity.getPersistentProperty("id"), "id");
accessor.put(entity.getPersistentProperty("b"), "b");
accessor.put(entity.getPersistentProperty("c"), "c");
DBObject nestedA = DBObjectTestUtils.getAsDBObject(target, "a");
assertThat(nestedA, is(notNullValue()));
assertThat(nestedA.get("b"), is((Object) "b"));
assertThat(nestedA.get("c"), is((Object) "c"));
}
static class ProjectingType { static class ProjectingType {
String name; String name;
@ -91,4 +113,10 @@ public class DBObjectAccessorUnitTests {
String c; String c;
} }
static class TypeWithTwoNestings {
String id;
@Field("a.b") String b;
@Field("a.c") String c;
}
} }

Loading…
Cancel
Save