簡體   English   中英

Spring Data MongoDB - 使用自定義 Id 字段時,注釋 @CreatedDate 不起作用

[英]Spring Data MongoDB - Annotation @CreatedDate does not work while using with custom Id field

我有一個簡單的持久化類:

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

和一個簡單的存儲庫:

public interface ProfileRepository extends MongoRepository<Profile, String> {

}

我的 Spring Boot Application 類也用 @EnableMongoAuditing 進行了注釋。 但我仍然無法獲得注釋 @CreatedDate 工作。

ProfileRepository.save(new Profile("user1")) 寫入沒有字段 createdDate 的實體。 我做錯了什么?

編輯:這是我的應用程序類(沒有@EnableMongoRepositories,但它可以工作,因為存儲庫在我猜的子包中)

@SpringBootApplication
@EnableMongoAuditing
public class Application {

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

編輯:同時添加注釋 EnableMongoRepositories 沒有改變任何東西。

我自己剛剛遇到了這個問題,這是因為您自己創建了 id。

public Profile(String username) {
        this.username = username;
    }

通過這樣做,mongo 認為它不是一個新對象並且不使用 @CreatedDate 注釋。 您還可以使用 @Document 批注而不是實現 Persistable 類,如下所示:

@Document
public class Profile{}

您只應該將提交的@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;
     }
 }

這是一個相關的問題: https : //jira.spring.io/browse/DATAMONGO-946

如果那是您真正的課程( Profile ),那么您無法使用標准工具做任何事情。

您的isNew方法將始終返回false ,因為您自己設置了用戶名,並且當Profile即將被 Spring 保存時,它會檢查isNew並且您可能已經設置了username @LastModifiedDate會在你的情況下工作,但@CreatedDate不會。

如果您沒有可以在isNew方法中使用的其他字段,那么您必須手動設置createdDate的值(或者可能有某種攔截器可以包裝所有 mongo 模板方法,但我不會那樣做) .

例如,檢查數據庫中是否已經存在具有給定用戶名的配置文件,如果是,則獲取它的 createdDate(您可以在此處使用投影)並設置為您將要保存的配置文件。 否則將 createdDate 設置為新日期。

如 Spring Data MongoDB 問題DATAMONGO-946中所述,創建日期功能使用isNew()方法來確定是否應設置創建日期,因為實體是新的。 在您的情況下,您的isNew方法始終返回 false,因為始終設置username

問題中的評論為這個問題提供了兩種可能的解決方案。

Persistable解決方案

第一個選項是修復isNew策略,以便它正確注冊新對象。 評論中建議的一種方法是更改​​實現以檢查createdDate字段本身,因為它應該只在非新對象上設置。

@Override
public boolean isNew() {
    return createdDate == null;
}

持久化實體解決方案

第二個選項是從實現Persistable改為使用持久化實體,並使用@Version注釋在持久化 MongoDB 實體中注入version屬性。 請注意,這改變數據的持久化方式,因為它向數據添加了一個自動遞增的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;
    }
}

我有一個類似的情況,我有時需要手動設置 id,如果不首先搜索數據庫來確定,真的沒有辦法提前知道 id 是新的還是更新的。 我也知道在實體的生命周期中,我會多次更新我的實體,但只創建一次。 所以為了避免額外的數據庫操作,我采用了這個解決方案:

    Profile savedProfile = profileRepo.save(profile);
    if (savedProfile.getCreatedDate() == null ){
        savedProfile.setCreatedDate(savedProfile.getLastModifiedDate());
        savedProfile = profileRepo.save(profile);
    }

這是利用這樣一個事實,即我在 Profile 上也有一個@LastModifiedDate字段,當保存實體時,該字段總是由 spring 數據更新。

對我來說,我只是這樣做:

    @CreatedDate
    @Field("created_date")
    @JsonIgnore
    private Instant createdDate = Instant.now();

並確保 Get/Set 可用。 希望這有幫助

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM