简体   繁体   English

Spring Data MongoDB - 使用自定义 Id 字段时,注释 @CreatedDate 不起作用

[英]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;
}

Persistent entity solution持久化实体解决方案

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.

相关问题 @CreatedDate 注解不适用于 spring-data-elasticsearch - @CreatedDate annotation does not work with spring-data-elasticsearch 手动分配 ID 时,Spring Data MongoDB Annotation @CreatedDate 不起作用 - Spring Data MongoDB Annotation @CreatedDate isn't working, when ID is assigned manually @CreatedDate 注释不适用于 mysql - @CreatedDate annotation does not work with mysql Spring 数据@CreatedDate 注释对我不起作用 - Spring Data @CreatedDate annotation doesn't work for me 审核(@CreatedDate)不适用于带有反应式 MongoDB 的 WebFlux Spring Boot - Auditing (@CreatedDate) does not work for WebFlux Spring Boot with reactive MongoDB 使用@DBRef批注进行引用时,MongoDB的Spring-Data异常 - Spring-Data for MongoDB exception while using @DBRef annotation for referencing spring-data-mongodb db-factory ID不起作用 - Spring-data-mongodb db-factory id does not work 简单的Spring @CreatedDate注释对我不起作用 - Simple Spring @CreatedDate annotation is not working for me 在Spring Data MongoDB中使用_id字段映射对象 - Mapping object with _id field in spring data mongodb Spring Controller:结合了Spring注释的自定义注释不起作用 - Spring Controller: Custom annotation with combined Spring annotations does not work
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM