[英]Spring Data MongoDB - Annotation @CreatedDate does not work while using with custom Id field
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.我的 Spring Boot Application 类也用 @EnableMongoAuditing 进行了注释。 But i still can't get the annotation @CreatedDate work.
但我仍然无法获得注释 @CreatedDate 工作。
ProfileRepository.save(new Profile("user1")) writes the entity without the field createdDate. ProfileRepository.save(new Profile("user1")) 写入没有字段 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)编辑:这是我的应用程序类(没有@EnableMongoRepositories,但它可以工作,因为存储库在我猜的子包中)
@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.编辑:同时添加注释 EnableMongoRepositories 没有改变任何东西。
I just ran into this problem myself, it happens because you are creating the id yourself.我自己刚刚遇到了这个问题,这是因为您自己创建了 id。
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.通过这样做,mongo 认为它不是一个新对象并且不使用 @CreatedDate 注释。 You could also use the @Document annotation instead of implementing the Persistable Class, like this:
您还可以使用 @Document 批注而不是实现 Persistable 类,如下所示:
@Document
public class Profile{}
You just ought to add @Version
filed to you @Document
class and left @EnableMongoAuditing
ie您只应该将提交的
@Version
添加到您的@Document
类并离开@EnableMongoAuditing
即
@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这是一个相关的问题: https : //jira.spring.io/browse/DATAMONGO-946
If that's your real class ( Profile
) then there's nothing you can do with standard tools.如果那是您真正的课程(
Profile
),那么您无法使用标准工具做任何事情。
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.您的
isNew
方法将始终返回false
,因为您自己设置了用户名,并且当Profile
即将被 Spring 保存时,它会检查isNew
并且您可能已经设置了username
。 @LastModifiedDate
would work in your case, but @CreatedDate
won't. @LastModifiedDate
会在你的情况下工作,但@CreatedDate
不会。
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).如果您没有可以在
isNew
方法中使用的其他字段,那么您必须手动设置createdDate
的值(或者可能有某种拦截器可以包装所有 mongo 模板方法,但我不会那样做) .
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.例如,检查数据库中是否已经存在具有给定用户名的配置文件,如果是,则获取它的 createdDate(您可以在此处使用投影)并设置为您将要保存的配置文件。 Otherwise set createdDate to new date.
否则将 createdDate 设置为新日期。
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.如 Spring Data MongoDB 问题DATAMONGO-946中所述,创建日期功能使用
isNew()
方法来确定是否应设置创建日期,因为实体是新的。 In your case, your isNew
method is always returning false, since the username
is always set.在您的情况下,您的
isNew
方法始终返回 false,因为始终设置username
。
The comments in the issue presents two possible solutions to this problem.问题中的评论为这个问题提供了两种可能的解决方案。
Persistable
solution Persistable
解决方案The first option is to fix the isNew
strategy so that it correctly registers new objects.第一个选项是修复
isNew
策略,以便它正确注册新对象。 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.评论中建议的一种方法是更改实现以检查
createdDate
字段本身,因为它应该只在非新对象上设置。
@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.第二个选项是从实现
Persistable
改为使用持久化实体,并使用@Version
注释在持久化 MongoDB 实体中注入version
属性。 Note that this will change how the data is persisted, as it adds an auto-incrementing version
field to the data.请注意,这将改变数据的持久化方式,因为它向数据添加了一个自动递增的
version
字段。
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;
}
}
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.我有一个类似的情况,我有时需要手动设置 id,如果不首先搜索数据库来确定,真的没有办法提前知道 id 是新的还是更新的。 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.这是利用这样一个事实,即我在 Profile 上也有一个
@LastModifiedDate
字段,当保存实体时,该字段总是由 spring 数据更新。
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.并确保 Get/Set 可用。 Hope this help
希望这有帮助
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.