我正在使用java和Spring。作为测试,我通过id查询对象,然后尝试保存同一个对象而不更新任何东西。当我这样做时,我得到一个重复的密钥异常。根据我读过的内容,如果_id为null,则MongoRepository.save()应该执行插入,否则应执行更新。显然,我应该得到更新。
一些代码:
// Succeeds
Datatype sut = mongoRepository.findOne("569eac0dd4c623dc65508679");
// Fails with duplicate key.
mongoRepository.save(sut);
为什么呢?重复上面的其他类的对象,他们工作。我怎么能麻烦拍这个呢?我不知道如何分解并解决问题。
由于
错误:
27906 [http-bio-8080-exec-3] 2016-05-02 13:00:26,304 DEBUG org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver -
Resolving exception from handler
[
public gov.nist.healthcare.tools.hl7.v2.igamt.lite.web.DatatypeSaveResponse
gov.nist.healthcare.tools.hl7.v2.igamt.lite.web.controller.DatatypeController.save(
gov.nist.healthcare.tools.hl7.v2.igamt.lite.domain.Datatype)
throws gov.nist.healthcare.tools.hl7.v2.igamt.lite.web.exception.DatatypeSaveException
]:
org.springframework.dao.DuplicateKeyException: {
"serverUsed" : "127.0.0.1:27017" ,
"ok" : 1 ,
"n" : 0 ,
"err" : "E11000 duplicate key error index: igl.datatype.$_id_ dup key: { : ObjectId('569eac0dd4c623dc65508679') }" ,
"code" : 11000};
nested exception is com.mongodb.MongoException$DuplicateKey: {
"serverUsed" : "127.0.0.1:27017" ,
"ok" : 1 ,
"n" : 0 ,
"err" : "E11000 duplicate key error index: igl.datatype.$_id_ dup key: { : ObjectId('569eac0dd4c623dc65508679') }" ,
"code" : 11000}
...重复
我刚刚发现了一个。如上所示保存时,spring会尝试插入,即使已填充_id。
保存其他对象(未显示但类似)时,弹簧执行,更新,再次填充是_id。
为何与众不同?文档说弹簧应该在填充_id时更新,并在不填充时插入。
还有什么可以造成这种情况吗?我的对象中有什么东西?也许我的读取转换器?
更新: 我刚见过这个团队。经过仔细审查,我们确定我们不再需要读取转换器。问题通过另一种方式解决了。
答案 0 :(得分:2)
使用读取转换器或写入转换器时,可以通过确保要保存的对象包含非null id字段来解决此问题。
SimpleMongoRepository在执行转换之前检查实体是否是新的。在我们的实例中,我们有一个没有id字段的对象,写转换器会添加它。
向对象添加一个填充的id字段将通知SimpleMongoRepository调用save而不是insert。
决定在这里发生。您的代码可能因Spring版本而异。希望对您有所帮助。
@Override
public <S extends T> S save(S entity) {
Assert.notNull(entity, "Entity must not be null!");
if (entityInformation.isNew(entity)) {
return mongoOperations.insert(entity, entityInformation.getCollectionName());
}
return mongoOperations.save(entity, entityInformation.getCollectionName());
}
答案 1 :(得分:0)
在数据库端,您可能已经创建了唯一索引。请查看“ https://docs.mongodb.com/manual/core/index-unique/”以了解更多信息。
答案 2 :(得分:0)
数据类型实体中的实现等于和哈希码方法,并确保mongoRepository扩展CrudRepositor (如https://docs.spring.io/spring-data/mongodb/docs/current/reference/html/#repositories中所述),以确保如果对象相等,则save方法应合并它们而不是保存新对象。