DATAMONGO-550 - Fixed potential NullPointerExceptions in MongoTemplate.
Guarded access to results of mappingContext.getPersistentEntity(…) to prevent NullPointerExceptions in case the template is used with non-entity types like a plain DBObject. Added some custom logic for plain BasicDBObjects to get the _id field populated appropriately.
This commit is contained in:
@@ -505,13 +505,12 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public <T> T findById(Object id, Class<T> entityClass) {
|
public <T> T findById(Object id, Class<T> entityClass) {
|
||||||
MongoPersistentEntity<?> persistentEntity = mappingContext.getPersistentEntity(entityClass);
|
return findById(id, entityClass, determineCollectionName(entityClass));
|
||||||
return findById(id, entityClass, persistentEntity.getCollection());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T> T findById(Object id, Class<T> entityClass, String collectionName) {
|
public <T> T findById(Object id, Class<T> entityClass, String collectionName) {
|
||||||
MongoPersistentEntity<?> persistentEntity = mappingContext.getPersistentEntity(entityClass);
|
MongoPersistentEntity<?> persistentEntity = mappingContext.getPersistentEntity(entityClass);
|
||||||
MongoPersistentProperty idProperty = persistentEntity.getIdProperty();
|
MongoPersistentProperty idProperty = persistentEntity == null ? null : persistentEntity.getIdProperty();
|
||||||
String idKey = idProperty == null ? ID : idProperty.getName();
|
String idKey = idProperty == null ? ID : idProperty.getName();
|
||||||
return doFindOne(collectionName, new BasicDBObject(idKey, id), null, entityClass);
|
return doFindOne(collectionName, new BasicDBObject(idKey, id), null, entityClass);
|
||||||
}
|
}
|
||||||
@@ -795,7 +794,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
|||||||
|
|
||||||
assertUpdateableIdIfNotSet(objectToSave);
|
assertUpdateableIdIfNotSet(objectToSave);
|
||||||
|
|
||||||
BasicDBObject dbDoc = new BasicDBObject();
|
DBObject dbDoc = new BasicDBObject();
|
||||||
|
|
||||||
maybeEmitEvent(new BeforeConvertEvent<T>(objectToSave));
|
maybeEmitEvent(new BeforeConvertEvent<T>(objectToSave));
|
||||||
writer.write(objectToSave, dbDoc);
|
writer.write(objectToSave, dbDoc);
|
||||||
@@ -982,7 +981,7 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
|||||||
Assert.notNull(object);
|
Assert.notNull(object);
|
||||||
|
|
||||||
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(object.getClass());
|
MongoPersistentEntity<?> entity = mappingContext.getPersistentEntity(object.getClass());
|
||||||
MongoPersistentProperty idProp = entity.getIdProperty();
|
MongoPersistentProperty idProp = entity == null ? null : entity.getIdProperty();
|
||||||
|
|
||||||
if (idProp == null) {
|
if (idProp == null) {
|
||||||
throw new MappingException("No id property found for object of type " + entity.getType().getName());
|
throw new MappingException("No id property found for object of type " + entity.getType().getName());
|
||||||
@@ -1438,6 +1437,12 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (savedObject instanceof BasicDBObject) {
|
||||||
|
DBObject dbObject = (DBObject) savedObject;
|
||||||
|
dbObject.put(ID, id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
MongoPersistentProperty idProp = getIdPropertyFor(savedObject.getClass());
|
MongoPersistentProperty idProp = getIdPropertyFor(savedObject.getClass());
|
||||||
|
|
||||||
if (idProp == null) {
|
if (idProp == null) {
|
||||||
@@ -1555,7 +1560,8 @@ public class MongoTemplate implements MongoOperations, ApplicationContextAware {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private MongoPersistentProperty getIdPropertyFor(Class<?> type) {
|
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) {
|
private <T> String determineEntityCollectionName(T obj) {
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||||||
import org.springframework.core.convert.converter.Converter;
|
import org.springframework.core.convert.converter.Converter;
|
||||||
import org.springframework.dao.DataAccessException;
|
import org.springframework.dao.DataAccessException;
|
||||||
import org.springframework.dao.DataIntegrityViolationException;
|
import org.springframework.dao.DataIntegrityViolationException;
|
||||||
|
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||||
import org.springframework.dao.OptimisticLockingFailureException;
|
import org.springframework.dao.OptimisticLockingFailureException;
|
||||||
import org.springframework.data.annotation.Id;
|
import org.springframework.data.annotation.Id;
|
||||||
import org.springframework.data.annotation.PersistenceConstructor;
|
import org.springframework.data.annotation.PersistenceConstructor;
|
||||||
@@ -63,6 +64,7 @@ import org.springframework.data.mongodb.core.query.Update;
|
|||||||
import org.springframework.test.context.ContextConfiguration;
|
import org.springframework.test.context.ContextConfiguration;
|
||||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||||
|
|
||||||
|
import com.mongodb.BasicDBObject;
|
||||||
import com.mongodb.DBCollection;
|
import com.mongodb.DBCollection;
|
||||||
import com.mongodb.DBCursor;
|
import com.mongodb.DBCursor;
|
||||||
import com.mongodb.DBObject;
|
import com.mongodb.DBObject;
|
||||||
@@ -143,6 +145,7 @@ public class MongoTemplateTests {
|
|||||||
template.dropCollection(TestClass.class);
|
template.dropCollection(TestClass.class);
|
||||||
template.dropCollection(Sample.class);
|
template.dropCollection(Sample.class);
|
||||||
template.dropCollection(MyPerson.class);
|
template.dropCollection(MyPerson.class);
|
||||||
|
template.dropCollection("collection");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -1352,6 +1355,44 @@ public class MongoTemplateTests {
|
|||||||
template.save(null);
|
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")));
|
||||||
|
}
|
||||||
|
|
||||||
static class MyId {
|
static class MyId {
|
||||||
|
|
||||||
String first;
|
String first;
|
||||||
|
|||||||
Reference in New Issue
Block a user