為了跟進該帖子,我將討論如何處理一些現實生活中的需求:處理更改的架構并自定義映射以處理諸如只讀字段之類的事情,并用復雜的對象替換簡單的字段。
變更架構
幾乎所有在開發領域中使用過數據庫的人都知道,模式一直在發展。 不推薦使用或完全刪除字段,廢棄表,添加新字段等等。
盡管通過使用像MongoDB這樣的無模式數據存儲可以避免很多麻煩,但有時我們仍然需要對更改進行特殊處理,就Morphia而言,我們本質上已經定義了模式,因此我們必須找到處理方法。這個。 最好的一點是,Morphia使它非常干凈和容易,比您在任何ORM中所看到的都要容易。
棄用字段
一個很好的例子是已被另一個字段替換的不推薦使用的字段。 假設您有一個錯誤跟蹤系統,其中包含如下所示的文檔:
{_id:1,desc: "IE Rendering broken on intranet site",componentName: "INTRANET",dateCreated: ISODate("2011-09-06T20:52:50.258Z")
}
這是Morphia的定義:
@Entity("issues")
class Issue {@Id private long id;private String desc;private String componentName;private Date dateCreated = new Date();
}
現在想象一下,我們決定取消組件字段,并使其成為更通用的自由文本字段,用戶可以在其中輸入多個組件,版本或其他有用信息。 我們不想僅僅將其放在組件字段中,因為那樣會導致混亂。
值得慶幸的是,我們在Morphia工具包中有專門針對此目的的東西– @AlsoLoad批注。 此批注允許我們用多個可能的來源之一填充POJO字段。 我們只需更新Morphia映射以指示舊字段名稱,就可以輕松刪除對舊字段的引用而不會破壞任何內容。 這樣可以使我們的代碼和文檔保持整潔。
@Entity("issues")
class Issue {@Id private long id;private String desc;@AlsoLoad("componentName") // handle old componentName fieldprivate String affects;private Date dateCreated = new Date();
}
因此,這里我們定義了舊字段的自動翻譯,而無需更新文檔或在POJO類中編寫特殊邏輯以根據創建時間的不同來處理文檔。
一個重要的提示:在這個例子中,如果這兩個領域的影響和舊的組件名稱字段存在,嗎啡會拋出異常,所以不要嘗試使用這種比自嘲領域,或者填充單場有兩個相互排斥的任何其他屬性。
僅支持不贊成使用的字段
另一種可能性是,您只需要在文檔中支持應用程序不再寫的舊字段即可。 這是一個非常簡單的方法:使用@NotSaved批注。 當您在字段上使用它時,數據將被加載,但Morphia不會寫入。
在前面的示例中,我們很容易決定僅支持舊字段的顯示,而不將其填充到情感字段中,因此讓我們對Morphia POJO進行一些更改以顯示如何使用@NotSaved 。
@Entity("issues")
class Issue {@Id private long id;private String desc;private String affects;@NotSaved("componentName") // load old componentName field for display onlyprivate String componentNameprivate Date dateCreated = new Date();
}
用嵌入式對象替換字段
現在,如果我們的componentName 字段實際上已更改為具有名稱,版本和內部版本號的復雜組件對象? 這有點棘手,因為我們想用多個替換一個字段。 我們不能嘗試從多個來源加載字段,因為它們的結構不同。 當然,我們可以使用嵌入式對象來存儲復雜的組件信息,但是如何使我們的代碼無縫地工作而不用更新我們的文檔呢?
在這種情況下,最簡單的方法是使用三個注釋的組合。 首先,我們將使用@NotSaved批注標記舊字段,并引入一個新的嵌入式組件 ? 對象使用@Embedded注釋 ,最后利用Morphia提供的另一個注釋– @PostLoad 。 這使我們有了一種從MongoDB填充POJO之后執行的方法。
這是示例:
@Entity("issues")
class Issue {@Id private long id;private String desc;private String affects;@NotSaved("componentName") // load old componentName to convert to componentprivate String componentName@Embedded // our new complex Componentprivate Component component;private Date dateCreated = new Date();// getters and setters ...@PostLoadprotected void handleComponent() {if (component == null && componentName != null) {component = new Component(componentName, null, null);}}
}class Component {private String componentName;private Long version;private Long buildNumber;public Component(String componentName, Long version, Long buildNumber) {// ...}// getters and setters ...
}
在這種情況下,我們可以刪除componentName字段的getter和setter,以便我們的映射對象僅公開新的和改進的接口。
結論
通過使用Morphia通過其注釋支持為我們提供的強大工具,我們可以實現以下目標:
- 讓我們的文檔結構適應應用程序并保持整潔。
- 在我們的Java代碼中無縫處理不斷變化的結構,而無需容易出錯的代碼。
- 在支持舊模式的同時僅公開新模式(確實淘汰了舊代碼和字段)。
希望這可以幫助你們中的一些人適應不斷發展的文檔,或者至少對這些Morphia注釋為您提供的功能更加熟悉。
參考: Morphia和MongoDB: Carfey軟件博客上來自我們JCG合作伙伴 Craig Flichel的不斷發展的文檔結構
翻譯自: https://www.javacodegeeks.com/2012/01/morphia-and-mongodb-evolving-document.html