From 74df4349edcade473a131cba619f847c9d52f394 Mon Sep 17 00:00:00 2001 From: Jon Brisbin Date: Wed, 16 Mar 2011 08:48:25 -0500 Subject: [PATCH] Use DBRefs instead of DBObjects so that save() will work. Now requires that a Mongo instance be set on the MappingMongoConverter, which is done from afterPropertiesSet() on the template. --- .../data/document/mongodb/MongoTemplate.java | 31 +++++--- .../convert/MappingMongoConverter.java | 73 ++++++++++++------- .../document/mongodb/mapping/Address.java | 4 +- .../mongodb/mapping/GenericMappingTests.java | 16 ++++ .../mongodb/mapping/MappingTests.java | 7 ++ 5 files changed, 94 insertions(+), 37 deletions(-) diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/MongoTemplate.java b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/MongoTemplate.java index 3c79d31ed..43054b705 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/MongoTemplate.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/MongoTemplate.java @@ -23,7 +23,16 @@ import java.util.Collections; import java.util.List; import java.util.Set; -import com.mongodb.*; +import com.mongodb.BasicDBObject; +import com.mongodb.CommandResult; +import com.mongodb.DB; +import com.mongodb.DBCollection; +import com.mongodb.DBCursor; +import com.mongodb.DBObject; +import com.mongodb.Mongo; +import com.mongodb.MongoException; +import com.mongodb.WriteConcern; +import com.mongodb.WriteResult; import com.mongodb.util.JSON; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -35,7 +44,7 @@ import org.springframework.core.convert.ConversionFailedException; import org.springframework.dao.DataAccessException; import org.springframework.dao.DataIntegrityViolationException; import org.springframework.data.document.mongodb.MongoPropertyDescriptors.MongoPropertyDescriptor; -import org.springframework.data.document.mongodb.convert.MongoConverter; +import org.springframework.data.document.mongodb.convert.MappingMongoConverter; import org.springframework.data.document.mongodb.convert.MongoConverter; import org.springframework.data.document.mongodb.convert.SimpleMongoConverter; import org.springframework.data.document.mongodb.query.IndexDefinition; @@ -1030,6 +1039,10 @@ public class MongoTemplate implements InitializingBean, MongoOperations { createCollection(getDefaultCollectionName(), null); } } + if (null != mongoConverter && mongoConverter instanceof MappingMongoConverter) { + ((MappingMongoConverter) mongoConverter).setMongo(mongo); + ((MappingMongoConverter) mongoConverter).setDefaultDatabase(databaseName); + } } @@ -1123,12 +1136,12 @@ public class MongoTemplate implements InitializingBean, MongoOperations { } } - public void setMongoConverter(MongoConverter converter) { - this.mongoConverter = converter; - } - - public void setWriteResultChecking(WriteResultChecking resultChecking) { - this.writeResultChecking = resultChecking; - } + public void setMongoConverter(MongoConverter converter) { + this.mongoConverter = converter; + } + + public void setWriteResultChecking(WriteResultChecking resultChecking) { + this.writeResultChecking = resultChecking; + } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/convert/MappingMongoConverter.java b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/convert/MappingMongoConverter.java index 5c1d5d392..3de89b155 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/convert/MappingMongoConverter.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/document/mongodb/convert/MappingMongoConverter.java @@ -19,12 +19,19 @@ package org.springframework.data.document.mongodb.convert; import java.lang.reflect.Array; import java.lang.reflect.InvocationTargetException; import java.math.BigInteger; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; import com.mongodb.BasicDBList; import com.mongodb.BasicDBObject; +import com.mongodb.DB; import com.mongodb.DBObject; import com.mongodb.DBRef; +import com.mongodb.Mongo; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.bson.types.ObjectId; @@ -40,7 +47,12 @@ import org.springframework.core.convert.support.GenericConversionService; import org.springframework.data.mapping.AssociationHandler; import org.springframework.data.mapping.MappingBeanHelper; import org.springframework.data.mapping.PropertyHandler; -import org.springframework.data.mapping.model.*; +import org.springframework.data.mapping.model.Association; +import org.springframework.data.mapping.model.MappingContext; +import org.springframework.data.mapping.model.MappingException; +import org.springframework.data.mapping.model.PersistentEntity; +import org.springframework.data.mapping.model.PersistentProperty; +import org.springframework.data.mapping.model.PreferredConstructor; import org.springframework.expression.Expression; import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.expression.spel.support.StandardEvaluationContext; @@ -59,6 +71,8 @@ public class MappingMongoConverter implements MongoConverter, ApplicationContext protected ApplicationContext applicationContext; protected boolean autowirePersistentBeans = false; protected boolean useFieldAccessOnly = true; + protected Mongo mongo; + protected String defaultDatabase; public MappingMongoConverter() { initializeConverters(); @@ -87,6 +101,22 @@ public class MappingMongoConverter implements MongoConverter, ApplicationContext this.mappingContext = mappingContext; } + public Mongo getMongo() { + return mongo; + } + + public void setMongo(Mongo mongo) { + this.mongo = mongo; + } + + public String getDefaultDatabase() { + return defaultDatabase; + } + + public void setDefaultDatabase(String defaultDatabase) { + this.defaultDatabase = defaultDatabase; + } + public boolean isAutowirePersistentBeans() { return autowirePersistentBeans; } @@ -369,10 +399,8 @@ public class MappingMongoConverter implements MongoConverter, ApplicationContext Collection coll = (type.isArray() ? Arrays.asList((Object[]) obj) : (Collection) obj); for (Object propObjItem : coll) { if (null != dbref) { - DBObject dbRefObj = createDBRef(propObjItem, dbref); - if (null != dbRefObj) { - dbList.add(dbRefObj); - } + DBRef dbRef = createDBRef(propObjItem, dbref); + dbList.add(dbRef); } else { BasicDBObject propDbObj = new BasicDBObject(); write(propObjItem, propDbObj, mappingContext.getPersistentEntity(prop.getTypeInformation())); @@ -386,10 +414,8 @@ public class MappingMongoConverter implements MongoConverter, ApplicationContext dbo.put(name, mapDbObj); } else { if (null != dbref) { - DBObject dbRefObj = createDBRef(obj, dbref); - if (null != dbRefObj) { - dbo.put(name, dbRefObj); - } + DBRef dbRef = createDBRef(obj, dbref); + dbo.put(name, dbRef); } else { BasicDBObject propDbObj = new BasicDBObject(); write(obj, propDbObj, mappingContext.getPersistentEntity(prop.getTypeInformation())); @@ -426,36 +452,37 @@ public class MappingMongoConverter implements MongoConverter, ApplicationContext } } - protected DBObject createDBRef(Object target, org.springframework.data.document.mongodb.mapping.DBRef dbref) { + protected DBRef createDBRef(Object target, org.springframework.data.document.mongodb.mapping.DBRef dbref) { PersistentEntity targetEntity = mappingContext.getPersistentEntity(target.getClass()); if (null == targetEntity || null == targetEntity.getIdProperty()) { return null; } - DBObject dbo = new BasicDBObject(); PersistentProperty idProperty = targetEntity.getIdProperty(); ObjectId id = null; try { id = MappingBeanHelper.getProperty(target, idProperty, ObjectId.class, useFieldAccessOnly); + if (null == id) { + throw new MappingException("Cannot create a reference to an object with a NULL id."); + } } catch (IllegalAccessException e) { throw new MappingException(e.getMessage(), e); } catch (InvocationTargetException e) { throw new MappingException(e.getMessage(), e); } - dbo.put("$id", id); String collection = dbref.collection(); if ("".equals(collection)) { collection = targetEntity.getType().getSimpleName().toLowerCase(); } - dbo.put("$ref", collection); - String db = dbref.db(); - if (!"".equals(db)) { - dbo.put("$db", db); + String dbname = dbref.db(); + if ("".equals(dbname)) { + dbname = defaultDatabase; } - return dbo; + DB db = mongo.getDB(dbname); + return new DBRef(db, collection, id); } @SuppressWarnings({"unchecked"}) @@ -510,13 +537,9 @@ public class MappingMongoConverter implements MongoConverter, ApplicationContext // It's a complex object, have to read it in if (dbo.containsField("_class")) { - try { - Class clazz = Class.forName(dbo.get("_class").toString()); - dbo.removeField("_class"); - o = read(clazz, (DBObject) dbObj); - } catch (ClassNotFoundException e) { - throw new MappingException(e.getMessage(), e); - } + Class toType = findTypeToBeUsed((DBObject) dbObj); + dbo.removeField("_class"); + o = read(toType, (DBObject) dbObj); } else { o = read(mappingContext.getPersistentEntity(prop.getTypeInformation()), (DBObject) dbObj); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/mapping/Address.java b/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/mapping/Address.java index 354e8ea81..eb6cb685b 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/mapping/Address.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/mapping/Address.java @@ -16,12 +16,10 @@ package org.springframework.data.document.mongodb.mapping; -import java.io.Serializable; - /** * @author Jon Brisbin */ -public class Address implements Serializable { +public class Address { private String[] lines; private String city; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/mapping/GenericMappingTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/mapping/GenericMappingTests.java index db1faac24..d8dca29ab 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/mapping/GenericMappingTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/mapping/GenericMappingTests.java @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2011 by the original author(s). + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.springframework.data.document.mongodb.mapping; import static org.hamcrest.CoreMatchers.is; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/mapping/MappingTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/mapping/MappingTests.java index 65aefd909..d87d043e5 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/mapping/MappingTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/document/mongodb/mapping/MappingTests.java @@ -134,6 +134,13 @@ public class MappingTests { p.setAccounts(accounts); template.insert("person", p); + Account newAcct = new Account(); + newAcct.setBalance(10000.00f); + template.insert("account", newAcct); + + accounts.add(newAcct); + template.save("person", p); + assertNotNull(p.getId()); }