Compare commits
7 Commits
1.1.0.RELE
...
1.1.1.RELE
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6323a86560 | ||
|
|
3b0b7315e1 | ||
|
|
4aeba6f92d | ||
|
|
342f9ae837 | ||
|
|
66d98b355e | ||
|
|
cabbe747f8 | ||
|
|
5ff3064acd |
2
pom.xml
2
pom.xml
@@ -6,7 +6,7 @@
|
||||
<name>Spring Data MongoDB Distribution</name>
|
||||
<description>Spring Data project for MongoDB</description>
|
||||
<url>http://www.springsource.org/spring-data/mongodb</url>
|
||||
<version>1.1.0.RELEASE</version>
|
||||
<version>1.1.1.RELEASE</version>
|
||||
<packaging>pom</packaging>
|
||||
<modules>
|
||||
<module>spring-data-mongodb</module>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||
<version>1.1.0.RELEASE</version>
|
||||
<version>1.1.1.RELEASE</version>
|
||||
<relativePath>../spring-data-mongodb-parent/pom.xml</relativePath>
|
||||
</parent>
|
||||
<artifactId>spring-data-mongodb-cross-store</artifactId>
|
||||
@@ -42,7 +42,7 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-mongodb</artifactId>
|
||||
<version>1.1.0.RELEASE</version>
|
||||
<version>1.1.1.RELEASE</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||
<version>1.1.0.RELEASE</version>
|
||||
<version>1.1.1.RELEASE</version>
|
||||
<relativePath>../spring-data-mongodb-parent/pom.xml</relativePath>
|
||||
</parent>
|
||||
<artifactId>spring-data-mongodb-log4j</artifactId>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<name>Spring Data MongoDB Parent</name>
|
||||
<description>Spring Data project for MongoDB</description>
|
||||
<url>http://www.springsource.org/spring-data/mongodb</url>
|
||||
<version>1.1.0.RELEASE</version>
|
||||
<version>1.1.1.RELEASE</version>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<developers>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||
<version>1.1.0.RELEASE</version>
|
||||
<version>1.1.1.RELEASE</version>
|
||||
<relativePath>../spring-data-mongodb-parent/pom.xml</relativePath>
|
||||
</parent>
|
||||
<artifactId>spring-data-mongodb</artifactId>
|
||||
|
||||
@@ -101,6 +101,7 @@ import com.mongodb.ReadPreference;
|
||||
import com.mongodb.WriteConcern;
|
||||
import com.mongodb.WriteResult;
|
||||
import com.mongodb.util.JSON;
|
||||
import com.mongodb.util.JSONParseException;
|
||||
|
||||
/**
|
||||
* Primary implementation of {@link MongoOperations}.
|
||||
@@ -505,13 +506,12 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
}
|
||||
|
||||
public <T> T findById(Object id, Class<T> entityClass) {
|
||||
MongoPersistentEntity<?> persistentEntity = mappingContext.getPersistentEntity(entityClass);
|
||||
return findById(id, entityClass, persistentEntity.getCollection());
|
||||
return findById(id, entityClass, determineCollectionName(entityClass));
|
||||
}
|
||||
|
||||
public <T> T findById(Object id, Class<T> entityClass, String collectionName) {
|
||||
MongoPersistentEntity<?> persistentEntity = mappingContext.getPersistentEntity(entityClass);
|
||||
MongoPersistentProperty idProperty = persistentEntity.getIdProperty();
|
||||
MongoPersistentProperty idProperty = persistentEntity == null ? null : persistentEntity.getIdProperty();
|
||||
String idKey = idProperty == null ? ID : idProperty.getName();
|
||||
return doFindOne(collectionName, new BasicDBObject(idKey, id), null, entityClass);
|
||||
}
|
||||
@@ -733,15 +733,20 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
}
|
||||
|
||||
public void save(Object objectToSave) {
|
||||
|
||||
Assert.notNull(objectToSave);
|
||||
save(objectToSave, determineEntityCollectionName(objectToSave));
|
||||
}
|
||||
|
||||
public void save(Object objectToSave, String collectionName) {
|
||||
|
||||
Assert.notNull(objectToSave);
|
||||
Assert.hasText(collectionName);
|
||||
|
||||
MongoPersistentEntity<?> mongoPersistentEntity = getPersistentEntity(objectToSave.getClass());
|
||||
|
||||
// No optimistic locking -> simple save
|
||||
if (!mongoPersistentEntity.hasVersionProperty()) {
|
||||
if (mongoPersistentEntity == null || !mongoPersistentEntity.hasVersionProperty()) {
|
||||
doSave(collectionName, objectToSave, this.mongoConverter);
|
||||
return;
|
||||
}
|
||||
@@ -786,14 +791,24 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected <T> void doSave(String collectionName, T objectToSave, MongoWriter<T> writer) {
|
||||
|
||||
assertUpdateableIdIfNotSet(objectToSave);
|
||||
|
||||
BasicDBObject dbDoc = new BasicDBObject();
|
||||
DBObject dbDoc = new BasicDBObject();
|
||||
|
||||
maybeEmitEvent(new BeforeConvertEvent<T>(objectToSave));
|
||||
writer.write(objectToSave, dbDoc);
|
||||
|
||||
if (!(objectToSave instanceof String)) {
|
||||
writer.write(objectToSave, dbDoc);
|
||||
} else {
|
||||
try {
|
||||
objectToSave = (T) JSON.parse((String) objectToSave);
|
||||
} catch (JSONParseException e) {
|
||||
throw new MappingException("Could not parse given String to save into a JSON document!", e);
|
||||
}
|
||||
}
|
||||
|
||||
maybeEmitEvent(new BeforeSaveEvent<T>(objectToSave, dbDoc));
|
||||
Object id = saveDBObject(collectionName, dbDoc, objectToSave.getClass());
|
||||
@@ -977,7 +992,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
Assert.notNull(object);
|
||||
|
||||
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(object.getClass());
|
||||
MongoPersistentProperty idProp = entity.getIdProperty();
|
||||
MongoPersistentProperty idProp = entity == null ? null : entity.getIdProperty();
|
||||
|
||||
if (idProp == null) {
|
||||
throw new MappingException("No id property found for object of type " + entity.getType().getName());
|
||||
@@ -993,7 +1008,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
private void assertUpdateableIdIfNotSet(Object entity) {
|
||||
|
||||
MongoPersistentEntity<?> persistentEntity = mappingContext.getPersistentEntity(entity.getClass());
|
||||
MongoPersistentProperty idProperty = persistentEntity.getIdProperty();
|
||||
MongoPersistentProperty idProperty = persistentEntity == null ? null : persistentEntity.getIdProperty();
|
||||
|
||||
if (idProperty == null) {
|
||||
return;
|
||||
@@ -1433,6 +1448,12 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
return;
|
||||
}
|
||||
|
||||
if (savedObject instanceof BasicDBObject) {
|
||||
DBObject dbObject = (DBObject) savedObject;
|
||||
dbObject.put(ID, id);
|
||||
return;
|
||||
}
|
||||
|
||||
MongoPersistentProperty idProp = getIdPropertyFor(savedObject.getClass());
|
||||
|
||||
if (idProp == null) {
|
||||
@@ -1550,7 +1571,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
||||
}
|
||||
|
||||
private MongoPersistentProperty getIdPropertyFor(Class<?> type) {
|
||||
return mappingContext.getPersistentEntity(type).getIdProperty();
|
||||
MongoPersistentEntity<?> persistentEntity = mappingContext.getPersistentEntity(type);
|
||||
return persistentEntity == null ? null : persistentEntity.getIdProperty();
|
||||
}
|
||||
|
||||
private <T> String determineEntityCollectionName(T obj) {
|
||||
|
||||
@@ -346,13 +346,14 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
}
|
||||
|
||||
final BeanWrapper<MongoPersistentEntity<Object>, Object> wrapper = BeanWrapper.create(obj, conversionService);
|
||||
|
||||
// Write the ID
|
||||
final MongoPersistentProperty idProperty = entity.getIdProperty();
|
||||
|
||||
if (!dbo.containsField("_id") && null != idProperty) {
|
||||
|
||||
boolean fieldAccessOnly = idProperty.usePropertyAccess() ? false : useFieldAccessOnly;
|
||||
|
||||
try {
|
||||
Object id = wrapper.getProperty(idProperty, Object.class, useFieldAccessOnly);
|
||||
Object id = wrapper.getProperty(idProperty, Object.class, fieldAccessOnly);
|
||||
dbo.put("_id", idMapper.convertId(id));
|
||||
} catch (ConversionException ignored) {
|
||||
}
|
||||
@@ -366,7 +367,9 @@ public class MappingMongoConverter extends AbstractMongoConverter implements App
|
||||
return;
|
||||
}
|
||||
|
||||
Object propertyObj = wrapper.getProperty(prop, prop.getType(), useFieldAccessOnly);
|
||||
boolean fieldAccessOnly = prop.usePropertyAccess() ? false : useFieldAccessOnly;
|
||||
|
||||
Object propertyObj = wrapper.getProperty(prop, prop.getType(), fieldAccessOnly);
|
||||
|
||||
if (null != propertyObj) {
|
||||
if (!conversions.isSimpleType(propertyObj.getClass())) {
|
||||
|
||||
@@ -27,6 +27,7 @@ import org.slf4j.LoggerFactory;
|
||||
import org.springframework.data.mapping.Association;
|
||||
import org.springframework.data.mapping.model.AnnotationBasedPersistentProperty;
|
||||
import org.springframework.data.mapping.model.SimpleTypeHolder;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.mongodb.DBObject;
|
||||
@@ -46,6 +47,8 @@ public class BasicMongoPersistentProperty extends AnnotationBasedPersistentPrope
|
||||
private static final Set<Class<?>> SUPPORTED_ID_TYPES = new HashSet<Class<?>>();
|
||||
private static final Set<String> SUPPORTED_ID_PROPERTY_NAMES = new HashSet<String>();
|
||||
|
||||
private static final Field CAUSE_FIELD;
|
||||
|
||||
static {
|
||||
SUPPORTED_ID_TYPES.add(ObjectId.class);
|
||||
SUPPORTED_ID_TYPES.add(String.class);
|
||||
@@ -53,6 +56,8 @@ public class BasicMongoPersistentProperty extends AnnotationBasedPersistentPrope
|
||||
|
||||
SUPPORTED_ID_PROPERTY_NAMES.add("id");
|
||||
SUPPORTED_ID_PROPERTY_NAMES.add("_id");
|
||||
|
||||
CAUSE_FIELD = ReflectionUtils.findField(Throwable.class, "cause");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -155,4 +160,12 @@ public class BasicMongoPersistentProperty extends AnnotationBasedPersistentPrope
|
||||
public boolean isVersionProperty() {
|
||||
return getField().isAnnotationPresent(Version.class);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.mapping.MongoPersistentProperty#usePropertyAccess()
|
||||
*/
|
||||
public boolean usePropertyAccess() {
|
||||
return CAUSE_FIELD.equals(getField());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,4 +80,12 @@ public interface MongoPersistentProperty extends PersistentProperty<MongoPersist
|
||||
return source.getFieldName();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether property access shall be used for reading the property value. This means it will use the getter
|
||||
* instead of field access.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
boolean usePropertyAccess();
|
||||
}
|
||||
|
||||
@@ -123,6 +123,13 @@ public class SimpleMongoMappingContext extends
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.mapping.MongoPersistentProperty#usePropertyAccess()
|
||||
*/
|
||||
public boolean usePropertyAccess() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static class SimpleMongoPersistentEntity<T> extends BasicPersistentEntity<T, MongoPersistentProperty> implements
|
||||
|
||||
@@ -24,8 +24,10 @@ import static org.springframework.data.mongodb.core.query.Update.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.bson.types.ObjectId;
|
||||
import org.joda.time.DateTime;
|
||||
@@ -40,9 +42,11 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.DataIntegrityViolationException;
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.dao.OptimisticLockingFailureException;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.annotation.PersistenceConstructor;
|
||||
import org.springframework.data.mapping.model.MappingException;
|
||||
import org.springframework.data.mongodb.InvalidMongoDbApiUsageException;
|
||||
import org.springframework.data.mongodb.MongoDbFactory;
|
||||
import org.springframework.data.mongodb.core.convert.CustomConversions;
|
||||
@@ -60,6 +64,7 @@ import org.springframework.data.mongodb.core.query.Update;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
import com.mongodb.BasicDBObject;
|
||||
import com.mongodb.DBCollection;
|
||||
import com.mongodb.DBCursor;
|
||||
import com.mongodb.DBObject;
|
||||
@@ -140,6 +145,7 @@ public class MongoTemplateTests {
|
||||
template.dropCollection(TestClass.class);
|
||||
template.dropCollection(Sample.class);
|
||||
template.dropCollection(MyPerson.class);
|
||||
template.dropCollection("collection");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1322,6 +1328,87 @@ public class MongoTemplateTests {
|
||||
assertThat(template.findAll(PersonWithConvertedId.class, collectionName).isEmpty(), is(true));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-549
|
||||
*/
|
||||
public void savesMapCorrectly() {
|
||||
|
||||
Map<String, String> map = new HashMap<String, String>();
|
||||
map.put("key", "value");
|
||||
|
||||
template.save(map, "maps");
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-549
|
||||
*/
|
||||
@Test(expected = MappingException.class)
|
||||
public void savesMongoPrimitiveObjectCorrectly() {
|
||||
template.save(new Object(), "collection");
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-549
|
||||
*/
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void rejectsNullObjectToBeSaved() {
|
||||
template.save(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-550
|
||||
*/
|
||||
@Test
|
||||
public void savesPlainDbObjectCorrectly() {
|
||||
|
||||
DBObject dbObject = new BasicDBObject("foo", "bar");
|
||||
template.save(dbObject, "collection");
|
||||
|
||||
assertThat(dbObject.containsField("_id"), is(true));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-550
|
||||
*/
|
||||
@Test(expected = InvalidDataAccessApiUsageException.class)
|
||||
public void rejectsPlainObjectWithOutExplicitCollection() {
|
||||
|
||||
DBObject dbObject = new BasicDBObject("foo", "bar");
|
||||
template.save(dbObject, "collection");
|
||||
|
||||
template.findById(dbObject.get("_id"), DBObject.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-550
|
||||
*/
|
||||
@Test
|
||||
public void readsPlainDbObjectById() {
|
||||
|
||||
DBObject dbObject = new BasicDBObject("foo", "bar");
|
||||
template.save(dbObject, "collection");
|
||||
|
||||
DBObject result = template.findById(dbObject.get("_id"), DBObject.class, "collection");
|
||||
assertThat(result.get("foo"), is(dbObject.get("foo")));
|
||||
assertThat(result.get("_id"), is(dbObject.get("_id")));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-551
|
||||
*/
|
||||
@Test
|
||||
public void writesPlainString() {
|
||||
template.save("{ 'foo' : 'bar' }", "collection");
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-551
|
||||
*/
|
||||
@Test(expected = MappingException.class)
|
||||
public void rejectsNonJsonStringForSave() {
|
||||
template.save("Foobar!", "collection");
|
||||
}
|
||||
|
||||
static class MyId {
|
||||
|
||||
String first;
|
||||
|
||||
@@ -918,7 +918,7 @@ public class MappingMongoConverterUnitTests {
|
||||
Object contacts = result.get("contacts");
|
||||
assertThat(contacts, is(instanceOf(Collection.class)));
|
||||
assertThat(((Collection<?>) contacts).size(), is(2));
|
||||
assertThat(((Collection<Object>) contacts), hasItem(nullValue()));
|
||||
assertThat((Collection<Object>) contacts, hasItem(nullValue()));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1310,6 +1310,19 @@ public class MappingMongoConverterUnitTests {
|
||||
assertThat(type.toString(), is("_"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-533
|
||||
*/
|
||||
@Test
|
||||
public void marshalsThrowableCorrectly() {
|
||||
|
||||
ThrowableWrapper wrapper = new ThrowableWrapper();
|
||||
wrapper.throwable = new Exception();
|
||||
|
||||
DBObject dbObject = new BasicDBObject();
|
||||
converter.write(wrapper, dbObject);
|
||||
}
|
||||
|
||||
static class GenericType<T> {
|
||||
T content;
|
||||
}
|
||||
@@ -1498,6 +1511,11 @@ public class MappingMongoConverterUnitTests {
|
||||
String name;
|
||||
}
|
||||
|
||||
static class ThrowableWrapper {
|
||||
|
||||
Throwable throwable;
|
||||
}
|
||||
|
||||
private class LocalDateToDateConverter implements Converter<LocalDate, Date> {
|
||||
|
||||
public Date convert(LocalDate source) {
|
||||
|
||||
@@ -68,6 +68,16 @@ public class BasicMongoPersistentPropertyUnitTests {
|
||||
getPropertyFor(ReflectionUtils.findField(Person.class, "ssn"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAMONGO-553
|
||||
*/
|
||||
@Test
|
||||
public void usesPropertyAccessForThrowableCause() {
|
||||
|
||||
MongoPersistentProperty property = getPropertyFor(ReflectionUtils.findField(Throwable.class, "cause"));
|
||||
assertThat(property.usePropertyAccess(), is(true));
|
||||
}
|
||||
|
||||
private MongoPersistentProperty getPropertyFor(Field field) {
|
||||
return new BasicMongoPersistentProperty(field, null, entity, new SimpleTypeHolder());
|
||||
}
|
||||
|
||||
@@ -1,6 +1,17 @@
|
||||
Spring Data MongoDB Changelog
|
||||
=============================================
|
||||
|
||||
Changes in version 1.1.1.GA (2012-10-17)
|
||||
----------------------------------------
|
||||
** Bug
|
||||
* [DATAMONGO-549] - MongoTemplate.save(…) suffers from potential NullPointException
|
||||
* [DATAMONGO-550] - MongoTemplate.save(BasicDBObject, String) results in NPE (after upgrading to 1.1.0.RELEASE
|
||||
* [DATAMONGO-551] - MongoTemplate.save(String, String) results in NPE (after upgrading to 1.1.0.RELEASE
|
||||
|
||||
** Task
|
||||
* [DATAMONGO-559] - Release 1.1.1.RELEASE
|
||||
|
||||
|
||||
Changes in version 1.1.0.GA (2012-10-10)
|
||||
----------------------------------------
|
||||
** Bug
|
||||
|
||||
Reference in New Issue
Block a user