簡體   English   中英

如果將屬性鍵入Object,為什么使用Spring Data MongoDB讀取嵌入式文檔會失敗?

[英]Why does reading embedded documents with Spring Data MongoDB fail if the property is typed to Object?

可以說我有以下Spring Data MongoDB接口:

public interface AccountRepository extends MongoRepository<Account, String> {}

現在,對象帳戶顯示在下面:

public class Account {

    @Id
    private String id;
    private Authentication authentication; //this is from the interface org.springframework.security.core.Authentication. Here I'm using org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken which implements the interface

當我調用下面的代碼時,Jackson將不會保存帳戶對象,因為我沒有可用於映射內部Authentication對象的Authentication模型。 此外,Jackson要求有一個Authentication()的公共空構造函數,而Spring Authentication類沒有這樣的構造函數:

 @Autowired
 AccountRepository accountRepo;

accountRepo.save(Account);

我必須將帳戶模型更改為以下內容,才能將身份驗證另存為對象:

public class Account {

    @Id
    private String id;
    private Object authentication;

但是,當我嘗試檢索身份驗證對象並將其重鑄到身份驗證對象時,出現此錯誤:

 {
  "timestamp": 1438441062525,
  "status": 500,
  "error": "Internal Server Error",
  "exception": "org.springframework.data.mapping.model.MappingException",
  "message": "No property aPrincipal found on entity class com.futureprocessing.spring.infrastructure.AuthenticatedExternalWebService to bind constructor parameter to!",
  "path": "/account"
}

我總是可以將身份驗證的各個部分分別保存在我的帳戶對象(委托人,憑據和授予權限)中,但是如果需要的話,我將必須做一個構造函數來重新創建它。

沒有簡單的方法可以將身份驗證對象另存為身份驗證對象?

tl; dr

由於對象模型的更改以及先前版本使用更強的類型,數據庫中已經存在的文檔不包含任何類型信息。 可以理解的是,這導致Spring Data MongoDB無法推斷出您想要讀取嵌入式Authentication時,它可以推斷出的只是Object類型的屬性。

細節

這里的問題是,當authentication屬性仍然是Authentication時,數據庫存儲了從類模型派生的文檔時,數據庫不包含任何類型信息。 如果在存儲時該屬性的值與聲明的屬性具有完全相同的類型,則Spring Data MongoDB不會寫入任何類型信息來避免額外的開銷。

如果您使用聲明為authentication屬性但包含Authentication對象的持久化Account ,Spring Data MongoDB將向嵌入的文檔中添加_class屬性以捕獲類型信息,以便在讀取文檔時映射器知道要實例化的類型。

如果在文檔中沒有該附加屬性,而在類型為Object的類中沒有authentication屬性,那么映射器將如何知道您在讀取文檔時要實例化Authentication對象?

解決方案

解決此問題的最簡單方法是手動向數據庫發布更新,並添加缺少的類型信息。 默認情況下,我們使用完全限定的類名,因此可以實現以下目的:

Update setTypeInformation = Update.update("authentication._class", Authentication.class.getName());
template.updateMulti(new Query(), setTypeInformation, Account.class);

Update語句將_class屬性添加到嵌入式authentication文檔中,並將其設置為Authentication的完全限定名稱。 由於與所有現有文檔匹配的空Query ,將對所有Accounts執行Update

更多參考

有關更多信息,請參見參考文檔的相應部分。

暫無
暫無

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

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