如何在Spring Data MongoDB 中保存和查詢動態字段


原文: https://stackoverflow.com/questions/46466562/how-to-save-and-query-dynamic-fields-in-spring-data-mongodb

MongoDB 的一大特點就是所有的記錄都是文檔形式,無所謂數據庫字段,每一條數據都是獨立的。在使用Spring Data MongoDB 時,如果直接用關系型數據庫的用法去套,那會發現很難發揮MongoDB的特性。

我在搜索如何解決問題的時候,發現了一篇問答正好能解決我的問題,所以我用自己淺薄的英語做個簡單的翻譯。

這是一篇 Stack Overflow 上的問答

有人提了個問題,在使用 Spring Boot 1.4.x 和 Spring Data MongoDB 時,想要動態存儲實體的字段,而不是直接用一個已經定義好的實體的固定字段存儲。

雖然可以在實體類內部創建一個Map屬性來存動態字段,但提問者想要的是所有的字段都處於MongoDB文檔的頂層,不想要在字段里面還存在額外的數據結構。

提問者嘗試后發現,直接將實體類繼承自HashMap是不行的

Error creating bean with name 'entryRepository': Invocation of init method failed; nested exception is org.springframework.data.mapping.model.MappingException: Could not lookup mapping metadata for domain class java.util.HashMap!

問題的優質回答:

先講結論:

  • 不能直接使用或者繼承java集合類作為實體類
  • Spring Data MongoDB 的 Repositories 不能實現上面的需求
  • 使用 DBObject 類配合 MongoTemplate 才能實現

分析;
Spring Data Repositories 是MongoDB用在設計好的數據結構中的持久層,為了配合面向對象設計使用。Spring Data 在分析檢查類的時候,會將集合和Map類型的類剔除出去。

Repository 的查詢方法雖然也可以實現動態字段查詢,但不是主流的用法。

public interface EntryRepository extends MongoRepository<Entry, String> {
    @Query("{ ?0 : ?1 }")
    Entry findByDynamicField(String field, Object value);
}

這個方法不提供任何類型安全檢查,只是簡陋地為字段提供一個別名。

最好使用 DBObject 配合 MongoTemplate 的Query方法使用。

List<DBObject> result = template.find(new Query(Criteria.where("your_dynamic_field").is(theQueryValue)), DBObject.class);

DBObject 能在不定義數據結構的情況下,直接映射MongoDB文檔的結果。可以直接使用 DBObject 類結合 MongoTemplate 進行增刪改查的操作。

我個人的嘗試

應該是 Spring Data MongoDB 相關團隊了解到了這個需求,目前的spring-data-mongodb 3.1.6 版本中,MongoTemplate 類的insert和save方法都可以直接操作Map數據,甚至對於任意實體類都能隨意操作,只要指定 collection 名稱就行。

HashMap object = new HashMap();
object.put("file_name", "object");
object.put("md5", "1827391");
HashMap aa = template.save(object, "file");

Student student = new Student("小明", "希望小學");
Student bb = template.save(student, "file");

以上代碼均能正常執行,數據能准確存入數據庫。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM