Reputation: 7215
I have a simple Persistable Class:
public class Profile implements Persistable<String>{
@Id
private String username;
@CreatedDate
public Date createdDate;
public Profile(String username) {
this.username = username;
}
@Override
public String getId() {
return username;
}
@Override
public boolean isNew() {
return username == null;
}
}
And a simple repository:
public interface ProfileRepository extends MongoRepository<Profile, String> {
}
My Spring Boot Application class is also annotated with @EnableMongoAuditing. But i still can't get the annotation @CreatedDate work.
ProfileRepository.save(new Profile("user1")) writes the entity without the field createdDate. What do i do wrong?
EDIT: This is my Application class (without @EnableMongoRepositories, but it works since the repositories are in the sub-packages i guess)
@SpringBootApplication
@EnableMongoAuditing
public class Application {
public static void main(String[] args) throws Exception {
SpringApplication.run(Application.class, args);
}
}
EDIT: Also adding the annotation EnableMongoRepositories did not change anything.
Upvotes: 7
Views: 16676
Reputation: 3896
simply just add @Version
field to you @Document
class and leave @EnableMongoAuditing
i.e.
@Document
public class Profile implements Persistable<String>{
@Version
private Long version;
@Id
private String username;
@CreatedDate
public Date createdDate;
public Profile(String username) {
this.username = username;
}
@Override
public String getId() {
return username;
}
@Override
public boolean isNew() {
return username == null;
}
}
Here is a related issue: https://jira.spring.io/browse/DATAMONGO-946
Upvotes: 7
Reputation: 21074
As described in Spring Data MongoDB issue DATAMONGO-946, the created date functionality uses the isNew()
method to determine whether the created date should be set since the entity is new. In your case, your isNew
method is always returning false, since the username
is always set.
The comments in the issue presents two possible solutions to this problem.
Persistable
solutionThe first option is to fix the isNew
strategy so that it correctly registers new objects. One way suggested in the comments would be to change the implementation to check the createdDate
field itself, since it should only be set on non-new objects.
@Override
public boolean isNew() {
return createdDate == null;
}
The second option is to change from implementing Persistable
to instead use a persistent entity and use the @Version
annotation to inject a version
property in the persisted MongoDB entity. Note that this will change how the data is persisted, as it adds an auto-incrementing version
field to the data.
import org.springframework.data.mongodb.core.mapping.Document;
@Document
public class Profile {
@Id
private String username;
@CreatedDate
public Date createdDate;
@Version
public Integer version;
public Profile(String username) {
this.username = username;
}
}
Upvotes: 2
Reputation: 71
I just ran into this problem myself, it happens because you are creating the id yourself.
public Profile(String username) {
this.username = username;
}
By doing this, mongo thinks it is not a new object and doesn't use the @CreatedDate annotation. You could also use the @Document annotation instead of implementing the Persistable Class, like this:
@Document
public class Profile{}
Upvotes: 5
Reputation: 6667
I have a similar situation where I needed to set the id manually sometimes and there really is no way to know ahead of time if the id will be a new one or an update without first searching the database to be sure. I also know that over the lifetime of the entity, I will be updating my entity many times, but creating it only once. So to avoid the extra database operations, I went with this solution:
Profile savedProfile = profileRepo.save(profile);
if (savedProfile.getCreatedDate() == null ){
savedProfile.setCreatedDate(savedProfile.getLastModifiedDate());
savedProfile = profileRepo.save(profile);
}
This is taking advantage of the fact that I also have a @LastModifiedDate
field on Profile as well that is always updated by spring data when an entity is saved.
Upvotes: -1
Reputation: 597
For me, i just do it as:
@CreatedDate
@Field("created_date")
@JsonIgnore
private Instant createdDate = Instant.now();
And make sure the Get/Set is available. Hope this help
Upvotes: -1
Reputation: 1954
If that's your real class (Profile
) then there's nothing you can do with standard tools.
Your isNew
method will always return false
, because you set the username by yourself and when Profile
is about to be saved by Spring it will check the isNew
and you probably have username
already set. @LastModifiedDate
would work in your case, but @CreatedDate
won't.
If you haven't got other fields that you can use in isNew
method then you have to set the value of createdDate
manually (or maybe there's some kind of interceptor that may wrap all mongo template method, but I wouldn't go that way).
For example, check if profile with given username already exists in DB, if so just get it's createdDate(you can use projection here) and set to the profile that you're about to save. Otherwise set createdDate to new date.
Upvotes: 1