SDN+OGM から SDN への移行

過去の SDN+OGM 移行に関する既知の課題

SDN+OGM には長年にわたってかなりの歴史があり、大規模なアプリケーションシステムの移行は楽しいものでも、すぐに利益が得られるものでもないことを理解しています。古いバージョンの Spring Data Neo4j から新しいバージョンに移行するときに確認された主な課題は、おおよそ次の順序で発生します。

複数のメジャーアップグレードをスキップした場合

Neo4j-OGM はスタンドアロンで使用できますが、Spring Data Neo4j はスタンドアロンで使用できません。これは Spring Data の拡張に大きく依存し、Spring Framework 自体にも大きく依存し、最終的にはアプリケーションの大部分に影響を与えます。アプリケーションがどのように構造化されているか、つまりフレームワーク部分がビジネスコードにどの程度漏れているかに応じて、アプリケーションを適応させる必要がさらに大きくなります。アプリケーションに複数の Spring Data モジュールがあり、グラフデータベースと同じサービス層にあるリレーショナルデータベースにアクセスした場合、事態はさらに悪化します。2 つのオブジェクトマッピングフレームワークを更新するのは楽しいことではありません。

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 に対して実行されることを確認する必要があります。これは、次の 3 つのケースのうち 2 つで動作することを意味します。

埋め込まれています

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://localhost:7687 のようなボルト URL を構成するか、ルーティングも処理する新しい neo4j:// スキームを使用する必要があります。

すでに Bolt を間接的に使用しています

デフォルトの SDN+OGM プロジェクトは org.neo4j:neo4j-ogm-bolt-driver を使用するため、間接的に Pure Java Driver を使用します。既存の 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://localhost:7687
spring.data.neo4j.username=neo4j
spring.data.neo4j.password=secret

# New
spring.neo4j.uri=bolt://localhost:7687
spring.neo4j.authentication.username=neo4j
spring.neo4j.authentication.password=secret
これらの新しいプロパティは、将来、SDN とドライバーが古い設定を完全に置き換えたときに、再び変更される可能性があります。

最後に、新しい依存関係を追加します。GradleMaven の両方については、入門を参照してください。

これで、アノテーションを置き換える準備が整いました。

古い 新規

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 に対応するアノテーションがまだ存在せず、今後も存在しないものもあります。追加の機能がサポートされると、上記のリストに追加されます。

ブックマーク管理

@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 は交換せずに取り外しました。なぜ? たとえスキーマのないデータベースであっても、スキーマの作成はドメインモデリングの一部ではないと考えています。SDN モデルがスキーマであると主張する人もいるかもしれませんが、コマンドとクエリの分離 [Wikipedia] (英語) の方が望ましいと答えるよりも、むしろ別々の読み取りモデルと書き込みモデルを定義することを意味します。これらは、「退屈な」ことを書いたり、グラフ状の回答を読んだりするのに非常に便利です。

それとは別に、これらのアノテーションの一部はそれぞれの値が特定の Neo4j エディションまたはバージョンに関連付けられているため、メンテナンスが困難になります。

ただし、最も有力な議論は本番環境です。スキーマを生成するすべてのツールは開発中に確かに役に立ちますが、厳格なスキームを強制するデータベースの場合はさらに役立ちますが、本番環境ではあまり役に立たない傾向があります。アプリケーションを同時に実行していますか ? バージョン A は、新しいバージョン B によって作成されたインデックスをアサートしますか ?

これについては事前に制御する方がよいと考えており、リキグラフ (英語) Neo4j の移行 [GitHub] (英語) などのツールに基づいて、制御されたデータベース移行を使用することをお勧めします。後者は、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 時点)。

暗号ベースの移行の例
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) と同等です。一意のインデックスにはすでにインデックスが含まれていることに注意してください。