MongoTemplate进行更新,并使用@ CreatedDate / @ LastModifiedDate

时间:2020-09-29 15:08:26

标签: java spring mongodb spring-data spring-data-mongodb

我有一个pojo,其外观如下:

@Document
public class MyPojo {
    @Id
    private String        id;
    ...
    @CreatedDate
    private ZonedDateTime createdAt;
    @LastModifiedDate
    private ZonedDateTime modifiedAt;
}

我要使用以下逻辑对文档进行增补:

  • 如果文档是新文档,则createdAtmodifiedAt都将设置为now
  • 如果该文档已存在,则createdAt不应更新,modifiedAt应该设置为now

我尝试使用以下代码:

MongoTemplate template = ...; // wired
MyPojo obj = new MyPojo();

template.findAndReplace(
        new Query().addCriteria(...),
        obj,
        new FindAndReplaceOptions().upsert());

此处,未设置成员idcreatedAtmodifiedAt(因此它们是null)。

这似乎不起作用。永远不会设置数据库中BSON文档中的相应字段。

如何结合@CreatedDate@LastModifiedDate批注来增补文档?这是可能的,还是我需要推出自己的产品。如果是后者,我如何实现如上所述的upsert逻辑?

我正在使用以下配置:

@Configuration
@EnableMongoAuditing(dateTimeProviderRef = "dateTimeConverter")

此处,dateTimeProviderRef用于支持ZonedDateTime对象。

,我注意到,在调用template.save(obj)template.insert(obj)而不是findAndReplace(...)(如我的代码段)时,createdAtmodifiedAt如预期般在创建时设置。就是说,我相信我需要findAndReplace(),因为我需要原子更新。

1 个答案:

答案 0 :(得分:0)

您需要通过在@SpringBootApplication上使用@EnableMongoAuditing启用审核

@SpringBootApplication
@EnableMongoAuditing(modifyOnCreate = false)
public class DemoApplication {

此外,不支持ZonedDateTime。请改为使用Instant。

参考:

请参见以下工作示例:

import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.mongodb.config.EnableMongoAuditing;
import org.springframework.data.mongodb.core.FindAndReplaceOptions;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.time.Instant;

import static org.springframework.data.mongodb.core.query.Criteria.where;
import static org.springframework.data.mongodb.core.query.Query.query;

@SpringBootApplication
@EnableMongoAuditing
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

@RestController
class Ctrl {
    @Autowired
    MongoTemplate template;

    @GetMapping("/templ")
    void templ() throws InterruptedException {
        template.insert(new MyPojo("TOM"));
        template.insert(new MyPojo("HARRY"));


        Thread.sleep(2000);

        //update BOB to Robert if exists or insert new
        //should inert new
        template.findAndReplace(
                query(where("name").is("BOB")),
                new MyPojo("Robert"),
                new FindAndReplaceOptions().upsert());


        Thread.sleep(2000);

        //update TOM to Tommy if exists or insert new
        template.findAndReplace(
                query(where("name").is("TOM")),
                new MyPojo("Tommy"),
                new FindAndReplaceOptions().upsert());


        template.findAll(MyPojo.class).forEach(System.out::println);
    }
}

@Document
@Data
@ToString
@NoArgsConstructor
class MyPojo {
    public MyPojo(String name) {
        this.name = name;
    }

    @Id
    private String id;
    String name = "";
    @CreatedDate
    private Instant createdAt;

    @LastModifiedDate
    private Instant modifiedAt;
}

输出:

MyPojo(id=5f736d33b72165754ea9fca1, name=Tommy, createdAt=2020-09-29T17:21:59.765Z, modifiedAt=null)
MyPojo(id=5f736d33b72165754ea9fca2, name=HARRY, createdAt=2020-09-29T17:21:55.732Z, modifiedAt=null)
MyPojo(id=5f736d352e78c143350ed0f8, name=Robert, createdAt=2020-09-29T17:21:57.748Z, modifiedAt=null)