and_rew and_rew - 12 days ago 9
Java Question

Spring Data MongoDB Annotation @CreatedDate isn't working, when ID is assigned manually

I'm trying to use auditing to save

dateCreated
and
dateUpdated
in my objects, but since I set
ID
manually, there's some additional work.

Following Oliver Gierke's suggestion in DATAMONGO-946
I'm trying to figure out how to correctly implement it.

As original poster in Jira task above, I've downloaded example from here https://github.com/spring-guides/gs-accessing-data-mongodb.git and modified it a bit:

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


and

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


and a result of execution is this:

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']


createdDate
becomes
null
after object update.

What am I missing here? And how to correctly implement
Persistable
to make auditing work properly?

Answer

Your code is working as expected. After you've implemented Persistable you can see that @CreatedDate annotation is working.

Sure that createdDate become null on second time because object already exist in the database and you update it with createdDate = null. As you can see from documentation for @CreatedDate:

@CreatedDate annotation. This identifies the field whose value is set when the entity is persisted to the database for the first time.

So to not overwrite your createdDate with null on second call you should retrieve your customer from database with c = repository.findOne("test_id"); and then update it.

Comments