使用Spring Data Mongo,我需要更新Mongo中的文档。
我的实体定义如下:
在writeInternal方法中,对文档的每个属性都进行了空值检查。如果属性为空,则在生成的DBObject中排除该属性。
这是一个非常丑陋的解决方案,因为Spring Data Mongo的MappingMongoConverter具有包可见性。Spring是否提供一种告诉我们:不要忽略带注释或其他东西的这些属性上的null值的方法?
谢谢。
下面是用于更新实体的代码。
我的实体定义如下:
@Document(collection = "Orders")
public class Order{
@Id
private Long id;
private String clientContainerReference;
private String status;
private Bigdecimal amount;
private BigDecimal remainingQuantity;
...
}
首先,将此文档插入Mongo时,其remainingQuantity为100。接下来,订单被更新为null的remainingQuantity。在更新(upsert)之后,remainingQuantity始终设置为100。
这是由于该类造成的:
org.springframework.data.mongodb.core.convert.MappingMongoConverter
在writeInternal方法中,对文档的每个属性都进行了空值检查。如果属性为空,则在生成的DBObject中排除该属性。
entity.doWithProperties(new PropertyHandler<MongoPersistentProperty>() {
public void doWithPersistentProperty(MongoPersistentProperty prop) {
if (prop.equals(idProperty)) {
return;
}
Object propertyObj = wrapper.getProperty(prop);
if (null != propertyObj) {
if (!conversions.isSimpleType(propertyObj.getClass())) {
writePropertyInternal(propertyObj, dbo, prop);
} else {
writeSimpleInternal(propertyObj, dbo, prop);
}
}
}
});
我明白这样做是更高效的,因为生成的DBObject较小,同时更新请求对于Mongo来说更容易处理。但如何更新真正的null值呢?
更具体地说,在我的情况下,所有文档的所有字段都可能为null。所以我不想编写自定义转换器,并且一个接一个地将每个Java字段映射到DBObject字段。
针对我的用例,我创建了一个名为“NullAwareMappingMongoConverter”的类,它重写了MappingMongoConverter,以便转换器在值为null时进行写入。
entity.doWithProperties(new PropertyHandler<MongoPersistentProperty>() {
public void doWithPersistentProperty(MongoPersistentProperty prop) {
if (prop.equals(idProperty)) {
return;
}
Object propertyObj = wrapper.getProperty(prop);
if (null != propertyObj) {
if (!conversions.isSimpleType(propertyObj.getClass())) {
writePropertyInternal(propertyObj, dbo, prop);
} else {
writeSimpleInternal(propertyObj, dbo, prop);
}
}
else{
writeSimpleInternal(propertyObj, dbo, prop);
}
}
});
这是一个非常丑陋的解决方案,因为Spring Data Mongo的MappingMongoConverter具有包可见性。Spring是否提供一种告诉我们:不要忽略带注释或其他东西的这些属性上的null值的方法?
谢谢。
下面是用于更新实体的代码。
public T setNotificationDateAndSave(T entity) {
Assert.notNull(entity, "Entity must not be null!");
BasicDBObject dbObject = new BasicDBObject();
mongoTemplate.getConverter().write(entity, dbObject);
DateTime expirationDate = getDeprecatedStatus().contains(getStatus(entity)) ?
new DateTime().plusSeconds(EXPIRE_AFTER_SECONDS) : null;
dbObject.put(EXPIRATION_DATE_COLUMN, mongoTemplate.getConverter()
.convertToMongoType(expirationDate, ClassTypeInformation.from(DateTime.class)));
NotificationDateUpdate update = new NotificationDateUpdate(dbObject, NOTIFICATION_DATE_COLUMN);
Query q = Query.query(Criteria.where("_id").is(entity.getId()).andOperator(Criteria.where(REGISTER_DATE_COLUMN).lte(entity.getRegisterDate())));
try{
mongoTemplate.upsert(q, update, parameterClass);
}catch (DuplicateKeyException e) {
logger.info(format("could not save notification : a more recent notification exists for collection %s and entity id : %s", parameterClass.getName(), entity.getId()));
}
return entity;
}
NotificationDateUpdate
是什么? - Oliver Drotbohm