從 SDN+OGM 遷移到 SDN
過去 SDN+OGM 遷移的已知問題
SDN+OGM 多年來一直有著豐富的歷史,我們理解遷移大型應用系統既不有趣也無法帶來即時利潤。我們在從舊版本 Spring Data Neo4j 遷移到新版本時觀察到的主要問題大致按以下順序排列:
- 跳過多次主要升級
-
雖然 Neo4j-OGM 可以獨立使用,但 Spring Data Neo4j 不行。它在很大程度上依賴於 Spring Data,進而依賴於 Spring Framework 本身,這最終會影響應用程式的很大一部分。根據應用程式的結構方式,也就是說,框架的任何部分滲透到業務程式碼的程度,您需要調整應用程式的程度就越大。如果您在應用程式中擁有多個 Spring Data 模組,或者在與圖資料庫相同的服務層訪問關係資料庫,情況會更糟。更新兩個物件對映框架並非易事。
- 依賴透過 Spring Data 本身配置的嵌入式資料庫
-
SDN+OGM 專案中的嵌入式資料庫由 Neo4j-OGM 配置。假設您想從 Neo4j 3.0 升級到 3.5,如果不升級整個應用程式,這是不可能的。為什麼會這樣?因為您選擇將資料庫嵌入到您的應用程式中,您就將自己繫結到了配置此嵌入式資料庫的模組。要擁有另一個嵌入式資料庫版本,您必須升級配置它的模組,因為舊模組不支援新資料庫。由於 Spring Data 版本始終與 Neo4j-OGM 相對應,您也必須升級它。然而,Spring Data 依賴於 Spring Framework,然後第一個要點中的論點適用。
- 不確定要包含哪些構建塊
-
正確理解這些術語並非易事。我們在此處撰寫了 SDN+OGM 設定的構建塊。可能所有這些都是偶然新增的,您正在處理大量衝突的依賴項。
| 根據這些觀察,我們建議在從 SDN+OGM 切換到 SDN 之前,確保您當前應用程式中僅使用 Bolt 或 HTTP 傳輸。因此,您的應用程式及其訪問層在很大程度上獨立於資料庫版本。從該狀態開始,考慮從 SDN+OGM 遷移到 SDN。 |
準備從 SDN+OGM Lovelace 或 SDN+OGM Moore 遷移到 SDN
| Lovelace 釋出列車對應於 SDN 5.1.x 和 OGM 3.1.x,而 Moore 對應於 SDN 5.2.x 和 OGM 3.2.x。 |
首先,您必須確保您的應用程式透過 Bolt 協議在伺服器模式下針對 Neo4j 執行,這意味著在三種情況中的兩種情況下需要工作
您正在使用嵌入式資料庫
您已將 org.neo4j:neo4j-ogm-embedded-driver 和 org.neo4j:neo4j 新增到您的專案中,並透過 OGM 工具啟動資料庫。這不再受支援,您必須設定一個標準的 Neo4j 伺服器(支援獨立和叢集)。
上述依賴項必須刪除。
從嵌入式解決方案遷移可能是最艱難的遷移,因為您還需要設定一個伺服器。然而,它本身會給您帶來很大價值:未來,您將能夠升級資料庫本身,而無需考慮您的應用程式框架以及資料訪問框架。
您正在使用 HTTP 傳輸
您已新增 org.neo4j:neo4j-ogm-http-driver 並配置了一個類似 user:password@localhost:7474 的 URL。該依賴項必須替換為 org.neo4j:neo4j-ogm-bolt-driver,並且您需要配置一個類似 bolt://:7687 的 Bolt URL,或者使用新的 neo4j:// 方案,該方案也負責路由。
遷移
一旦您確保您的 SDN+OGM 應用程式透過 Bolt 正常工作,您就可以開始遷移到 SDN。
-
刪除所有
org.neo4j:neo4j-ogm-*依賴項 -
不支援透過
org.neo4j.ogm.config.Configurationbean 配置 SDN,相反,所有驅動程式配置都透過我們新的 Java 驅動程式啟動器進行。您尤其需要調整 URL 和身份驗證的屬性,請參閱 新舊屬性對比
| 您不能透過 XML 配置 SDN。如果您使用 SDN+OGM 應用程式執行此操作,請確保您瞭解 Spring 應用程式的註解驅動或函式式配置。如今最簡單的選擇是 Spring Boot。有了我們的啟動器,除了連線 URL 和身份驗證之外的所有必要配置都已經為您完成。 |
# Old
spring.data.neo4j.embedded.enabled=false # No longer supported
spring.data.neo4j.uri=bolt://:7687
spring.data.neo4j.username=neo4j
spring.data.neo4j.password=secret
# New
spring.neo4j.uri=bolt://:7687
spring.neo4j.authentication.username=neo4j
spring.neo4j.authentication.password=secret
| 這些新屬性將來可能會再次更改,當 SDN 和驅動程式最終完全替換舊設定時。 |
最後,新增新的依賴項,請參閱 Gradle 和 Maven 的入門。
然後您就可以替換註解了
| 舊 | 新 |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
無替換,不再需要 |
|
無替換,不再需要 |
|
使用投影;不再支援任意結果對映 |
| 一些 Neo4j-OGM 註解在 SDN 中尚未有相應的註解,有些永遠不會有。我們將隨著我們支援更多功能而新增到上述列表中。 |
書籤管理
@EnableBookmarkManagement 和 @UseBookmark 以及 org.springframework.data.neo4j.bookmark.BookmarkManager 介面及其唯一的實現 org.springframework.data.neo4j.bookmark.CaffeineBookmarkManager 都已移除且不再需要。
SDN 在所有事務中都使用書籤,無需配置。您可以刪除 CaffeineBookmarkManager 的 bean 宣告以及對 com.github.ben-manes.caffeine:caffeine 的依賴。
如果您絕對需要,可以按照這些說明停用自動書籤管理。
自動建立約束和索引
SDN 5.3 及更早版本提供了 Neo4j-OGM 的“自動索引管理器”。
@Index、@CompositeIndex 和 @Required 已被移除,沒有替代。為什麼?我們認為建立 schema(即使對於無 schema 資料庫)不屬於領域建模的一部分。您可以爭辯說 SDN 模型就是 schema,但我們會回答說我們更喜歡命令查詢分離,這意味著我們寧願定義單獨的讀寫模型。這些對於編寫“無聊”的東西和讀取圖形狀的答案非常方便。
除此之外,其中一些註解及其值與特定的 Neo4j 版本或版本繫結,這使得它們難以維護。
然而,最好的論點是投入生產:雖然所有生成 schema 的工具在開發過程中確實有幫助,尤其是在強制執行嚴格 schema 的資料庫中,但它們在生產中往往不太好:如何處理同時執行的不同版本的應用程式?版本 A 斷言由較新版本 B 建立的索引?
我們認為最好提前控制這一點,並建議使用受控的資料庫遷移,基於 Liquigraph 或 Neo4j migrations 等工具。後者已在 JHipster 專案內部與 SDN 一起使用。這兩個專案的共同點是它們將 schema 的當前版本儲存在資料庫中,並確保 schema 在更新之前符合預期。
從以前的 Neo4j-OGM 註解遷移會影響 @Index、@CompositeIndex 和 @Required,此處 使用 Neo4j-OGM 自動索引管理器的類中給出了這些示例
import org.neo4j.ogm.annotation.CompositeIndex;
import org.neo4j.ogm.annotation.GeneratedValue;
import org.neo4j.ogm.annotation.Id;
import org.neo4j.ogm.annotation.Index;
import org.neo4j.ogm.annotation.Required;
@CompositeIndex(properties = {"tagline", "released"})
public class Movie {
@Id @GeneratedValue Long id;
@Index(unique = true)
private String title;
private String description;
private String tagline;
@Required
private Integer released;
}
它的註解等同於 Cypher 中的以下模式(截至 Neo4j 4.2)
CREATE CONSTRAINT movies_unique_title ON (m:Movie) ASSERT m.title IS UNIQUE;
CREATE CONSTRAINT movies_released_exists ON (m:Movie) ASSERT EXISTS (m.released);
CREATE INDEX movies_tagline_released_idx FOR (m:Movie) ON (m.tagline, m.released);
使用 @Index 而不帶 unique = true 等同於 CREATE INDEX movie_title_index FOR (m:Movie) ON (m.title)。請注意,唯一索引已經暗示了一個索引。