java - Spring Boot mongo审核@version问题

标签 java spring mongodb spring-boot spring-data

我刚刚开始一个新项目,想使用 Sprint Boot 2.1,但一开始就遇到了问题。我想做的是使用 Spring Boot Mongo 来管理数据库。我想要一个带有 @Version 注释的乐观锁。但是,我发现 @Version 似乎会影响 MongoRepository 中的 save() 行为,这意味着 dup key 错误。

下面是示例代码。

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 中,但在第二次 save 时出现 dup key 错误,这意味着它尝试插入 再次,即使对象中有 id。
我还尝试在 version 字段中使用 Long ,该字段没有发生重复 key 并按预期保存为更新,但 createdOn 变为 第一个保存中为 null(这意味着插入)

Controller

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());

使用 dup key 记录(长版本)

    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') }

创建日期为空的日志(长版本)

    2018-11-11 02:07:28.858  INFO 4310 --- [on(6)-127.0.0.1] org.mongodb.driver.connection            : Opened connection [connectionId{localValue:2, serverValue:183}] to localhost:27017
    Person [id=null, name=Joe, email=aa@aa.aa, createdOn=null, modifiedOn=null, version=null]
    2018-11-11 02:07:31.519 DEBUG 4310 --- [nio-8080-exec-1] o.s.data.auditing.AuditingHandler        : Touched Person [id=null, name=Joe, email=aa@aa.aa, createdOn=null, modifiedOn=2018-11-11T02:07:31.518, version=0] - Last modification at 2018-11-11T02:07:31.518 by unknown
    2018-11-11 02:07:31.525 DEBUG 4310 --- [nio-8080-exec-1] o.s.data.mongodb.core.MongoTemplate      : Inserting Document containing fields: [modifiedOn, version, name, email, _class] in collection: person
    2018-11-11 02:07:31.564 DEBUG 4310 --- [nio-8080-exec-1] o.s.d.m.r.query.MongoQueryCreator        : Created query Query: { "name" : "Joe" }, Fields: { }, Sort: { }
    2018-11-11 02:07:31.571 DEBUG 4310 --- [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=5be71e631ad34410d6a3b123, name=Joe, email=aa@aa.aa, createdOn=null, modifiedOn=2018-11-11T02:07:31.518, version=0]
    2018-11-11 02:07:31.590 DEBUG 4310 --- [nio-8080-exec-1] o.s.data.auditing.AuditingHandler        : Touched Person [id=5be71e631ad34410d6a3b123, name=Joe, email=bb@bb.bb, createdOn=null, modifiedOn=2018-11-11T02:07:31.590, version=1] - Last modification at 2018-11-11T02:07:31.590 by unknown
    2018-11-11 02:07:31.598 DEBUG 4310 --- [nio-8080-exec-1] o.s.data.mongodb.core.MongoTemplate      : Calling update using query: { "_id" : { "$oid" : "5be71e631ad34410d6a3b123" }, "version" : { "$numberLong" : "0" } } and update: { "modifiedOn" : { "$date" : 1541873251590 }, "version" : { "$numberLong" : "1" }, "name" : "Joe", "email" : "bb@bb.bb", "_class" : "com.seedu.server.model.Person" } in collection: person
    2018-11-11 02:07:31.602 DEBUG 4310 --- [nio-8080-exec-1] o.s.d.m.r.query.MongoQueryCreator        : Created query Query: { "name" : "Joe" }, Fields: { }, Sort: { }
    2018-11-11 02:07:31.602 DEBUG 4310 --- [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
    2018-11-11 02:07:31.603 DEBUG 4310 --- [nio-8080-exec-1] o.s.d.m.r.query.MongoQueryCreator        : Created query Query: { "email" : "bb@bb.bb" }, Fields: { }, Sort: { }
    2018-11-11 02:07:31.604 DEBUG 4310 --- [nio-8080-exec-1] o.s.data.mongodb.core.MongoTemplate      : find using query: { "email" : "bb@bb.bb" } fields: Document{{}} for class: class com.seedu.server.model.Person in collection: person
    Person [id=5be71e631ad34410d6a3b123, name=Joe, email=bb@bb.bb, createdOn=null, modifiedOn=2018-11-11T02:07:31.590, version=1]
    Person [id=5be71e631ad34410d6a3b123, name=Joe, email=bb@bb.bb, createdOn=null, modifiedOn=2018-11-11T02:07:31.590, version=1]

据我所知,spring使用id存在作为保存行为控制,这意味着如果id存在则save就像mongo的插入一样。然而,在这里,版本似乎也影响保存行为或影响 spring 识别 id 存在的方式。

问题:如何将 MongoAudit 与 MongoRepository 一起使用?我犯了什么错误/错误吗?

最佳答案

要使用@Version,您必须首先从数据库中检索数据模型,并在更新数据后,必须将相同的数据保存到数据库中。 例如:

  personRepo.findByName(name).ifPresent(person-> {
            person.setEmail("email@gamil.com");
            personRepo.save(person);
            log.info("Updated Data: {}", person);
        });
如果您没有将 @Version 添加到模型类中,

@CreatedDate 将始终为 null。它适用于@Version

如果您没有将 @Version 添加到模型类中,并且您尝试使用模型类 @Version 来更新相同的模型,则还需要在此处添加一点,它会再次给你重复的 id 错误。

关于java - Spring Boot mongo审核@version问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53242033/

相关文章:

java - Android studio从html获取数据并仅过滤一些值以在textView上显示

java - SchedulerFactory 是否能够在启动时为 quartz 创建表?

java - Android PopupWindow showAtLocation() vs showAsDropDown() - 第一个对我有用,第二个不是

javascript - 通过 Meteor 从数组中提取条目

java - 如何使用JAVA UUID中的.net GUID作为mongodb集合的主键

java - 我的不同 session 使用相同的最后一个 Activity 和 session ID 进行重复,为什么?

java - Roaster:如何提供带有注释的自定义参数值?

java - 在Java中检测字符串中重复字符的最有效方法是什么?

java - Spring + thymeleaf : ResourceManager : unable to find resource 'index.vm' in any resource loader

java - Spring security - authorizerequest()、anyRequest() 和authenticated() 有什么作用?