我刚开始一个新项目,并且想使用Sprint Boot 2.1并在一开始就遇到了问题。我想做的是使用Spring Boot Mongo来管理数据库。我想使用@Version
注释进行乐观锁定。但是,我发现@Version
似乎会影响MongoRepository中的save()
行为,这意味着dup键错误。
以下是示例代码。
POJO
@Data
@AllArgsConstructor
@NoArgsConstructor
@Document
public class Person {
@Id public ObjectId id;
@CreatedDate public LocalDateTime createOn;
@LastModifiedDate public LocalDateTime modifiedOn;
@Version public long version;
private String name;
private String email;
public Person(String name, String email) {
this.name = name;
this.email = email;
}
@Override
public String toString() {
return String.format("Person [id=%s, name=%s, email=%s, createdOn=%s, modifiedOn=%s, version=%s]", id, name, email, createOn, modifiedOn, version);
}
}
MongoConfig
@Configuration
@EnableMongoRepositories("com.project.server.repo")
@EnableMongoAuditing
public class MongoConfig {
}
存储库
public interface PersonRepo extends MongoRepository<Person, ObjectId> {
Person save(Person person);
Person findByName(String name);
Person findByEmail(String email);
long count();
@Override
void delete(Person person);
}
如Official Doc所示,我在version
中有我的long
字段,但是dup键错误发生在第二个save
上,这意味着它试图{{ 1}},即使对象中包含id。
我还尝试在insert
字段中使用Long
,没有发生重复密钥,并按预期方式保存为更新,但是version
在第一个{{1}中成为createdOn
}(表示null
)
控制器
save
带有复制键的日志(insert
)
Person joe = new Person("Joe", "aa@aa.aa");
System.out.println(joe.toString());
this.personRepo.save(joe);
Person who = this.personRepo.findByName("Joe");
System.out.println(who.toString());
who.setEmail("bb@bb.bb");
this.personRepo.save(who);
Person who1 = this.personRepo.findByName("Joe");
Person who2 = this.personRepo.findByEmail("bb@bb.bb");
System.out.println(who1.toString());
System.out.println(who2.toString());
创建日期为空的日志(long version
)
2018-11-11 02:09:31.435 INFO 4319 --- [on(6)-127.0.0.1] org.mongodb.driver.connection : Opened connection [connectionId{localValue:2, serverValue:186}] to localhost:27017
Person [id=null, name=Joe, email=aa@aa.aa, createdOn=null, modifiedOn=null, version=0]
2018-11-11 02:09:37.254 DEBUG 4319 --- [nio-8080-exec-1] o.s.data.auditing.AuditingHandler : Touched Person [id=null, name=Joe, email=aa@aa.aa, createdOn=2018-11-11T02:09:37.252, modifiedOn=2018-11-11T02:09:37.252, version=0] - Last modification at 2018-11-11T02:09:37.252 by unknown
2018-11-11 02:09:37.259 DEBUG 4319 --- [nio-8080-exec-1] o.s.data.mongodb.core.MongoTemplate : Inserting Document containing fields: [createOn, modifiedOn, version, name, email, _class] in collection: person
2018-11-11 02:09:37.297 DEBUG 4319 --- [nio-8080-exec-1] o.s.d.m.r.query.MongoQueryCreator : Created query Query: { "name" : "Joe" }, Fields: { }, Sort: { }
2018-11-11 02:09:37.304 DEBUG 4319 --- [nio-8080-exec-1] o.s.data.mongodb.core.MongoTemplate : find using query: { "name" : "Joe" } fields: Document{{}} for class: class com.seedu.server.model.Person in collection: person
Person [id=5be71ee11ad34410df06852c, name=Joe, email=aa@aa.aa, createdOn=2018-11-11T02:09:37.252, modifiedOn=2018-11-11T02:09:37.252, version=0]
2018-11-11 02:09:37.323 DEBUG 4319 --- [nio-8080-exec-1] o.s.data.auditing.AuditingHandler : Touched Person [id=5be71ee11ad34410df06852c, name=Joe, email=bb@bb.bb, createdOn=2018-11-11T02:09:37.323, modifiedOn=2018-11-11T02:09:37.323, version=0] - Last modification at 2018-11-11T02:09:37.323 by unknown
2018-11-11 02:09:37.324 DEBUG 4319 --- [nio-8080-exec-1] o.s.data.mongodb.core.MongoTemplate : Inserting Document containing fields: [_id, createOn, modifiedOn, version, name, email, _class] in collection: person
org.springframework.dao.DuplicateKeyException: E11000 duplicate key error collection: seedu.person index: _id_ dup key: { : ObjectId('5be71ee11ad34410df06852c') }; nested exception is com.mongodb.MongoWriteException: E11000 duplicate key error collection: seedu.person index: _id_ dup key: { : ObjectId('5be71ee11ad34410df06852c') }
据我所知,spring使用id的存在作为保存行为的控件,这意味着,如果id存在,那么保存就像mongo的插入一样。但是,在这里,版本似乎也会影响保存行为或影响spring识别id的方式。
问题:如何将MongoAudit与MongoRepository一起使用?我有任何错误/错误吗?
答案 0 :(得分:1)
我仍然不知道问题所在。但是,尽管我的设置与上面的发布完全相同,但是由于我将Spring Boot从2.1.0升级到2.1.1,所以现在一切正常(无论我使用的是哪种类型的版本,Long / long)< / p>
以下是我现在正在使用的库版本。
spring-boot-starter-data-mongodb:2.1.1.RELEASE:
-> spring-data-mongo:2.1.3.RELEASE
-> mongodb-driver:3.8.2
答案 1 :(得分:0)
要使用@Version
,必须首先从数据库中检索数据模型,更新数据后,必须将相同的数据保存到数据库中。
例如:
personRepo.findByName(name).ifPresent(person-> {
person.setEmail("email@gamil.com");
personRepo.save(person);
log.info("Updated Data: {}", person);
});
如果您没有将@CreatedDate
添加到模型类,则 null
将始终为@Version
。与@Version
如果您没有在模型类中添加@Version
,并且尝试通过添加模型类@Version
来进行更新,则可以在此处再添加一点,它将再次为您提供重复的ID错误。