我正在使用Spring Data Mongo存储库来保存我的实体。所有实体的父类如下所示: -
@Document
public abstract class AbstractEntity {
@Id
private String id;
@CreatedDate
private Date dateCreated;
@LastModifiedDate
private Date lastUpdated;
@Version
private Long version; // This is creating trouble while 'update' operation
}
这是我配置Mongo存储库和审计的方式: -
@Configuration
@EnableMongoRepositories(basePackages = { "x.y.z" })
@EnableMongoAuditing
@EnableAutoConfiguration
public class MongoRepositoryConfig {
}
我可以保存并更新'我的实体到Mongo,直到我没有在我的实体中包含@Version字段进行审核。
如果我在我的实体类中使用@Version审核字段,在尝试使用MongoRepository#save(entity)方法更新实体/文档时,我会遇到以下异常: -
Caused by: com.mongodb.MongoException$DuplicateKey: { "serverUsed" : "localhost:27017" , "ok" : 1 , "n" : 0 , "err" : "insertDocument :: caused by :: 11000 E11000 duplicate key error index: test.MENU_ITEM.$_id_ dup key: { : ObjectId('541ed581f39d6f87787067e3') }" , "code" : 11000}
at com.mongodb.CommandResult.getWriteException(CommandResult.java:88)
at com.mongodb.CommandResult.getException(CommandResult.java:79)
at com.mongodb.DBCollectionImpl.translateBulkWriteException(DBCollectionImpl.java:314)
at com.mongodb.DBCollectionImpl.insert(DBCollectionImpl.java:189)
at com.mongodb.DBCollectionImpl.insert(DBCollectionImpl.java:165)
at com.mongodb.DBCollection.insert(DBCollection.java:93)
at com.mongodb.DBCollection.insert(DBCollection.java:78)
at com.mongodb.DBCollection.insert(DBCollection.java:120)
at org.springframework.data.mongodb.core.MongoTemplate$8.doInCollection(MongoTemplate.java:900)
at org.springframework.data.mongodb.core.MongoTemplate.execute(MongoTemplate.java:410)
当实体有@Version时,为什么upsert操作失败?据我所知,版本字段用于更新操作时的乐观锁定。
保存保存方法似乎是尝试执行插入操作而不是更新。这是@Version的预期行为吗?
<spring.data.mongo.version>1.6.0.RELEASE</spring.data.mongo.version>
答案 0 :(得分:5)
清理Mongo数据库解决了这个问题。
在我的域类中添加@Version Long版本属性之前,我在集合中没有版本属性的现有mongo文档很少。这导致了这个问题。
答案 1 :(得分:0)
您似乎正在尝试保存哪个版本与mongo集合中的文档不匹配的文档。它未设置或某个旧值设置为版本。 MongoDB使用@version进行乐观锁定,这意味着它将数据库中的文档版本与正在保存的实体上的版本相匹配。如果版本不匹配,则会引发错误。
尝试下面的代码,它可以帮助您解决此错误。
public void updateUser(String userId, String password) {
//Before updating a document for specified userId, fetch the latest document from db
Login userFromDB = loginRepository.findOne(userId);
userFromDB.setPassword(password); //set the field to be updated
userRepository.save(userFromDB); //this will overwrite the document in database with new pwd
}
在保存时,MongoDB将增加版本号。