当手动分配ID时,Spring Data MongoDB Annotation @CreatedDate不起作用

and*_*rew 9 java spring mongodb spring-data spring-data-mongodb

我正在尝试使用审计来保存dateCreated并保存dateUpdated在我的对象中,但是由于我ID手动设置,还有一些额外的工作.

遵循Oliver GierkeDATAMONGO-946中提出的建议, 我试图找出如何正确实现它.

作为上面Jira任务的原始海报,我从这里下载了示例https://github.com/spring-guides/gs-accessing-data-mongodb.git并对其进行了一些修改:

package hello;

import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.domain.Persistable;

import java.util.Date;

public class Customer implements Persistable<String> {
    @Id
    private String id;
    @CreatedDate
    private Date createdDate;
    @LastModifiedDate
    private Date lastModifiedDate;
    private String firstName;
    private String lastName;
    private boolean persisted;

    public Customer() {
    }

    public Customer(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }

    public void setPersisted(boolean persisted) {
        this.persisted = persisted;
    }

    @Override
    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    @Override
    public boolean isNew() {
        return !persisted;
    }

    @Override
    public String toString() {
        return String.format(
                "Customer[id=%s, createdDate=%s, lastModifiedDate=%s, firstName='%s', lastName='%s']",
                id, createdDate, lastModifiedDate, firstName, lastName);
    }
}
Run Code Online (Sandbox Code Playgroud)

package hello;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.mongodb.config.EnableMongoAuditing;

@SpringBootApplication
@EnableMongoAuditing
public class Application implements CommandLineRunner {

    @Autowired
    private CustomerRepository repository;

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @Override
    public void run(String... args) throws Exception {

        repository.deleteAll();

        // create a customer
        Customer c = new Customer("Alice", "Smith");
        c.setId("test_id");

        // save a customer
        repository.save(c);

        // fetch all customers
        System.out.println("Customers found with findAll():");
        System.out.println("-------------------------------");
        for (Customer customer : repository.findAll()) {
            System.out.println(customer);
        }
        System.out.println();

        // create another customer with same id
        c = new Customer("Bob", "Smith");
        c.setId("test_id");
        c.setPersisted(true);
        repository.save(c);

        // fetch all customers
        System.out.println("Customers found with findAll():");
        System.out.println("-------------------------------");
        for (Customer customer : repository.findAll()) {
            System.out.println(customer);
        }
        System.out.println();
    }
}
Run Code Online (Sandbox Code Playgroud)

执行结果如下:

Customers found with findAll():
-------------------------------
Customer[id=test_id, createdDate=Wed Feb 24 00:43:47 WITA 2016, lastModifiedDate=Wed Feb 24 00:43:47 WITA 2016, firstName='Alice', lastName='Smith']

Customers found with findAll():
-------------------------------
Customer[id=test_id, createdDate=null, lastModifiedDate=Wed Feb 24 00:43:47 WITA 2016, firstName='Bob', lastName='Smith']
Run Code Online (Sandbox Code Playgroud)

createdDatenull在对象更新后变为.

我在这里错过了什么?如何正确实施Persistable审计工作?

小智 16

添加@EnableMongoAuditing到 Spring Boot 应用程序的 main 方法中。


Ore*_*est 9

您的代码按预期工作.实施后,Persistable您可以看到@CreatedDate注释正在运行.

当然,这createdDatenull第二次调用,save因为该对象已经存在于数据库中并且您使用它进行了更新createdDate = null.正如您从文档中看到的@CreatedDate:

@CreatedDate注释.这标识了当实体第一次持久保存到数据库时设置其值的字段.

因此,不要在第二次调用时覆盖你的createdDate,null你应该从数据库中检索你的客户c = repository.findOne("test_id");,然后更新它.

  • 我同意and_rew.我希望使用@CreatedDate注释的字段可以使用初始插入日期进行设置,并将该值保留在后续更新中.我为什么要在更新时删除创建日期?审计的重点是保留这些信息. (4认同)
  • 谢谢你,奥雷斯特。看起来就像你描述的那样。但这意味着我需要自己管理这个领域。那为什么我需要注释呢?它不就是为了自动管理这些字段而创建的吗?也许只有当 ID 也自动生成时。 (2认同)

小智 6

最简单的解决方案是向 Customer 类添加版本属性(用 @Version 注释)并保持其未初始化。这会将 0 值分配给任何新创建的对象,这又告诉 spring 这是一个新对象。

  @Version private Long version;
Run Code Online (Sandbox Code Playgroud)

注意:此对象的每次修改都会自动增加此版本