從 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,如果您不升級整個應用程式,這是不可能的。為什麼會這樣?因為您選擇了將資料庫嵌入到您的應用程式中,您就將自己與配置這個嵌入式資料庫的模組繫結在了一起。要使用另一個嵌入式資料庫版本,您必須升級配置它的模組,因為舊模組不支援新資料庫。由於總是存在與 Neo4j-OGM 相對應的 Spring Data 版本,您也必須升級它。然而,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-driverorg.neo4j:neo4j 新增到您的專案中,並透過 OGM 工具啟動資料庫。這不再受支援,您必須設定一個標準的 Neo4j 伺服器(支援獨立版和叢集版)。

必須刪除上述依賴項。

從嵌入式解決方案遷移可能是最困難的遷移,因為您還需要設定一個伺服器。然而,它本身也為您帶來了很大的價值:將來,您可以升級資料庫本身,而無需考慮您的應用程式框架和資料訪問框架。

您使用 HTTP 傳輸

您已新增 org.neo4j:neo4j-ogm-http-driver 並配置了一個類似 user:password@localhost:7474 的 URL。該依賴項必須替換為 org.neo4j:neo4j-ogm-bolt-driver,並且您需要配置一個 Bolt URL,例如 bolt://:7687,或者使用新的 neo4j:// 方案,後者也負責路由。

您已間接使用 Bolt

預設的 SDN+OGM 專案使用 org.neo4j:neo4j-ogm-bolt-driver,因此間接使用了純 Java 驅動程式。您可以保留現有的 URL。

遷移

一旦您確保您的 SDN+OGM 應用程式透過 Bolt 正常工作,就可以開始遷移到 SDN。

  • 刪除所有 org.neo4j:neo4j-ogm-* 依賴項

  • 不再支援透過 org.neo4j.ogm.config.Configuration Bean 配置 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 的配置請參閱入門

然後您就可以替換註解了

org.neo4j.ogm.annotation.NodeEntity

org.springframework.data.neo4j.core.schema.Node

org.neo4j.ogm.annotation.GeneratedValue

org.springframework.data.neo4j.core.schema.GeneratedValue

org.neo4j.ogm.annotation.Id

org.springframework.data.neo4j.core.schema.Id

org.neo4j.ogm.annotation.Property

org.springframework.data.neo4j.core.schema.Property

org.neo4j.ogm.annotation.Relationship

org.springframework.data.neo4j.core.schema.Relationship

org.springframework.data.neo4j.annotation.EnableBookmarkManagement

無替代,不再需要

org.springframework.data.neo4j.annotation.UseBookmark

無替代,不再需要

org.springframework.data.neo4j.annotation.QueryResult

使用投影;不再支援任意結果對映

有幾個 Neo4j-OGM 註解在 SDN 中還沒有對應的註解,有些永遠不會有。隨著我們支援更多功能,我們將新增到上面的列表中。

Bookmark 管理

@EnableBookmarkManagement@UseBookmark,以及 org.springframework.data.neo4j.bookmark.BookmarkManager 介面及其唯一實現 org.springframework.data.neo4j.bookmark.CaffeineBookmarkManager 都已移除,不再需要。

SDN 在所有事務中都使用 bookmarks,無需配置。您可以移除 CaffeineBookmarkManager 的 Bean 宣告以及對 com.github.ben-manes.caffeine:caffeine 的依賴。

如果絕對必要,您可以按照這些說明停用自動 bookmark 管理。

自動建立約束和索引

SDN 5.3 及更早版本提供了 Neo4j-OGM 的“自動索引管理器”。

@Index, @CompositeIndex@Required 已被移除,沒有替代。為什麼?我們認為建立模式——即使對於無模式資料庫——也不屬於領域建模的一部分。您可能會爭辯說 SDN 模型就是模式,但我們會回答說我們甚至更喜歡命令-查詢分離,這意味著我們更願意定義獨立的讀模型和寫模型。這對於編寫“枯燥”的東西和讀取圖狀答案非常方便。

除此之外,其中一些註解及其值與特定的 Neo4j 版本或版本繫結,這使得它們難以維護。

然而,最好的論據是面向生產:雖然所有生成模式的工具在開發過程中確實很有幫助,尤其是在強制嚴格模式的資料庫中,但在生產環境中它們往往不太友好:如何處理同時執行的不同版本的應用程式?版本 A 斷言新版本 B 建立的索引?

我們認為最好提前控制這一點,並建議使用基於 LiquigraphNeo4j migrations 等工具的受控資料庫遷移。後者已在 JHipster 專案中與 SDN 一起使用。這兩個專案的共同點是它們在資料庫內部儲存當前模式版本,並在更新之前確保模式符合預期。

從先前的 Neo4j-OGM 註解遷移會影響 @Index@CompositeIndex@Required,並且在使用 Neo4j-OGM 自動索引管理器的類中給出了一個示例。

使用 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)

基於 Cypher 的遷移示例
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);

使用不帶 unique = true@Index 等同於 CREATE INDEX movie_title_index FOR (m:Movie) ON (m.title)。請注意,唯一索引本身就隱含著索引。