入門

SDN 用に Spring Boot スターターを提供します。依存関係管理を介してスターターモジュールを含め、使用するボルト URL ( spring.neo4j.uri=bolt://localhost:7687 など) を構成してください。スターターは、サーバーが認証を無効にしていると想定します。SDN スターターは Java ドライバーのスターターに依存するため、そこに記載されている設定に関するすべての内容がここにも当てはまります。使用可能なプロパティのリファレンスについては、spring.neo4j 名前空間の IDE の自動補完を使用してください。

SDN のサポート

これらはすべて同じバイナリに含まれています。リアクティブプログラミングモデルでは、データベース側に 4 つ以上の Neo4j サーバーが必要で、一方でリアクティブ Spring が必要です。

データベースを準備する

この例では、すべての Neo4j インスタンスにフリーで付属しているため、ムービーグラフ (英語) 内に留まります。

実行中のデータベースはないが、Docker がインストールされている場合は、次を実行してください。

Docker 内でローカル Neo4j インスタンスを開始します。
docker run --publish=7474:7474 --publish=7687:7687 -e 'NEO4J_AUTH=neo4j/secret' neo4j:5

これで http://localhost:7474 にアクセスできるようになります。上記のコマンドは、サーバーのパスワードを secret に設定します。プロンプトでコマンドを実行する準備ができていることに注目してください (:play movies)。これを実行して、データベースにテストデータを入力します。

新しい Spring Boot プロジェクトを作成する

Spring Boot プロジェクトをセットアップする最も簡単な方法は start.spring.io です (Web サイトを使用したくない場合に備えて、主要な IDE にも統合されています)。

"Spring Web Starter" を選択して、Spring ベースの Web アプリケーションの作成に必要なすべての依存関係を取得します。Spring Initializr は、選択したビルドツールのすべてのファイルと設定を使用して、有効なプロジェクト構造を作成します。

Maven の使用

Spring イニシャライザーに対して curl リクエストを発行して、基本的な Maven プロジェクトを作成できます。

Spring Initializr を使用して基本的な Maven プロジェクトを作成する
curl https://start.spring.io/starter.tgz \
  -d dependencies=webflux,data-neo4j  \
  -d bootVersion=3.4.5 \
  -d baseDir=Neo4jSpringBootExample \
  -d name=Neo4j%20SpringBoot%20Example | tar -xzvf -

これにより、新しいフォルダー Neo4jSpringBootExample が作成されます。このスターターはまだイニシャライザーにないため、次の依存関係を pom.xml に手動で追加する必要があります。

Maven プロジェクトへの spring-data-neo4j-spring-boot-starter の組み込み
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-data-neo4j</artifactId>
</dependency>

既存のプロジェクトの場合は、依存関係を手動で追加することもできます。

Gradle の使用

考え方は同じで、Gradle プロジェクトを生成するだけです。

Spring Initializr を使用して基本的な Gradle プロジェクトを作成する
curl https://start.spring.io/starter.tgz \
  -d dependencies=webflux,data-neo4j \
  -d type=gradle-project \
  -d bootVersion=3.4.5 \
  -d baseDir=Neo4jSpringBootExampleGradle \
  -d name=Neo4j%20SpringBoot%20Example | tar -xzvf -

Gradle の依存関係は次のようになり、build.gradle に追加する必要があります。

Gradle プロジェクトへの spring-data-neo4j-spring-boot-starter の組み込み
dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-data-neo4j'
}

既存のプロジェクトの場合は、依存関係を手動で追加することもできます。

プロジェクトを構成する

次に、これらのプロジェクトのいずれかをお気に入りの IDE で開きます。application.properties を見つけて、Neo4j 認証情報を構成します。

spring.neo4j.uri=bolt://localhost:7687
spring.neo4j.authentication.username=neo4j
spring.neo4j.authentication.password=verysecret

これは、Neo4j インスタンスに接続するために必要な最低限のものです。

このスターターを使用する場合、ドライバーのプログラム構成を追加する必要はありません。SDN リポジトリは、このスターターによって自動的に有効になります。

Neo4j Cypher-DSL の構成

アプリケーションを実行する Neo4j のバージョンに応じて、Neo4j Cypher-DSL を実行するダイアレクトを設定することをお勧めします。デフォルトで使用されるダイアレクトは、Neo4j の LTS バージョンとして Neo4j 4.4 をターゲットにしています。これは、Cypher-DSL Configuration Bean を定義することで変更できます。

Cypher-DSL に Neo4j 5 ダイアレクトを使用させる
@Bean
Configuration cypherDslConfiguration() {
	return Configuration.newConfig()
                .withDialect(Dialect.NEO4J_5).build();
}
Spring Data Neo4j は、Neo4j 5 とデフォルトのダイアレクトの組み合わせとも互換性があるように最善を尽くしますが、ダイアレクトを明示的に定義することを常にお勧めします。例: これにより、クエリがより最適化され、新しい Neo4j バージョンで elementId() が使用されるようになります。

モジュールパス上で実行

Spring Data Neo4j はモジュールパス上で実行できます。自動モジュール名は spring.data.neo4j です。現在の Spring Data ビルドセットアップの制限により、モジュール自体は提供されません。自動ではあるが安定したモジュール名が使用されます。ただし、モジュール化されたライブラリ ( サイファー DSL [GitHub] (英語) ) に依存します。上記の制限により module-info.java がなければ、お客様に代わってそのライブラリの要件を表明することはできません。

モジュールパスで Spring Data Neo4j 6.1+ を実行するためにプロジェクトで最低限必要な module-info.java は次のとおりです。

モジュールパスで Spring Data Neo4j を使用することになっているプロジェクト内の module-info.java 
module your.module {

	requires org.neo4j.cypherdsl.core;

	requires spring.data.commons;
	requires spring.data.neo4j;

	opens your.domain to spring.core; (1)

	exports your.domain; (2)
}
1Spring Data Neo4j は Spring Data Commons とそのリフレクティブ機能を使用するため、少なくともドメインパッケージを spring.core に開く必要があります。
2 ここでは、your.domain にはリポジトリも含まれていると仮定します。これらは、spring.beansspring.contextspring.data.commons からアクセスできるようにエクスポートする必要があります。世界にエクスポートしたくない場合は、それらのモジュールに制限できます。

ドメインを作成する

ドメイン層は次の 2 つのことを達成する必要があります。

  • グラフをオブジェクトにマッピングする

  • それらへのアクセスを提供する

ノードエンティティの例

SDN は、Kotlin の Java クラスと data クラスの両方で、変更不可能なエンティティを完全にサポートします。ここでは不変エンティティに焦点を当てます。MovieEntity.java はそのようなエンティティを示します。

SDN は、Neo4j Java ドライバーがサポートするすべてのデータ型をサポートします。「Cypher 型システム」の章内の Neo4j 型をネイティブ言語型にマッピングする (英語) を参照してください。将来のバージョンでは追加のコンバーターがサポートされる予定です。
MovieEntity.java
import java.util.ArrayList;
import java.util.List;

import org.springframework.data.neo4j.core.schema.Id;
import org.springframework.data.neo4j.core.schema.Node;
import org.springframework.data.neo4j.core.schema.Property;
import org.springframework.data.neo4j.core.schema.Relationship;
import org.springframework.data.neo4j.core.schema.Relationship.Direction;

@Node("Movie") (1)
public class MovieEntity {

	@Id (2)
	private final String title;

	@Property("tagline") (3)
	private final String description;

	@Relationship(type = "ACTED_IN", direction = Direction.INCOMING) (4)
	private List<Roles> actorsAndRoles = new ArrayList<>();

	@Relationship(type = "DIRECTED", direction = Direction.INCOMING)
	private List<PersonEntity> directors = new ArrayList<>();

	public MovieEntity(String title, String description) { (5)
		this.title = title;
		this.description = description;
	}

	// Getters omitted for brevity
}
1@Node は、このクラスを管理対象エンティティとしてマークするために使用されます。Neo4j ラベルの構成にも使用されます。プレーンな @Node を使用している場合、ラベルはデフォルトでクラスの名前になります。
2 各エンティティには ID が必要です。ここに示すムービークラスは、一意のビジネスキーとして属性 title を使用します。このような一意のキーがない場合は、@Id と @GeneratedValue を組み合わせて、Neo4j の内部 ID を使用するように SDN を構成できます。UUID のジェネレーターも提供します。
3 これは、グラフプロパティとは異なるフィールド名を使用する方法として @Property を示しています。
4 これは、型 PersonEntity のクラスおよび関連型 ACTED_IN への関連を定義します。
5 これは、アプリケーションコードで使用されるコンストラクターです。

一般論として: SDN では、データベースによって生成された値をフィールドに設定する方法が必要であるため、内部生成された ID を使用する不変エンティティは少し矛盾しています。

適切なビジネスキーが見つからない場合、または ID のジェネレーターを使用したくない場合は、内部的に生成された ID を通常のコンストラクターと、SDN で使用されるいわゆるウィザー -Method とともに使用する同じエンティティを次に示します。

MovieEntity.java
import org.springframework.data.neo4j.core.schema.GeneratedValue;
import org.springframework.data.neo4j.core.schema.Id;
import org.springframework.data.neo4j.core.schema.Node;
import org.springframework.data.neo4j.core.schema.Property;

import org.springframework.data.annotation.PersistenceConstructor;

@Node("Movie")
public class MovieEntity {

	@Id @GeneratedValue
	private Long id;

	private final String title;

	@Property("tagline")
	private final String description;

	public MovieEntity(String title, String description) { (1)
		this.id = null;
		this.title = title;
		this.description = description;
	}

	public MovieEntity withId(Long id) { (2)
		if (this.id.equals(id)) {
			return this;
		} else {
			MovieEntity newObject = new MovieEntity(this.title, this.description);
			newObject.id = id;
			return newObject;
		}
	}
}
1 これは、アプリケーションコードで使用されるコンストラクターです。内部 ID を含むフィールドは決して操作されるべきではないため、ID を null に設定します。
2id -attribute のいわゆる枯れです。元のエンティティを変更せずに、新しいエンティティを作成し、それに応じてフィールドを設定することで、エンティティを不変にします。

もちろん、Kotlin (英語) で SDN を使用し、Kotlin のデータクラスでドメインをモデル化することもできます。プロジェクト Lombok (英語) は、純粋に Java 内に留まりたい、またはその必要がある場合の代替手段です。

Spring Data リポジトリの宣言

ここには基本的に 2 つのオプションがあります。SDN をストアに依存しないメソッドで作業することと、ドメイン固有の拡張を次の 1 つにすることができます。

  • org.springframework.data.repository.Repository

  • org.springframework.data.repository.CrudRepository

  • org.springframework.data.repository.reactive.ReactiveCrudRepository

  • org.springframework.data.repository.reactive.ReactiveSortingRepository

それに応じて命令型とリアクティブ型を選択します。

技術的には禁止されていませんが、同じアプリケーション内で命令型データベースアクセスとリアクティブデータベースアクセスを混在させることはお勧めできません。このようなシナリオについてはサポートしません。

もう 1 つのオプションは、ストア固有の実装に落ち着いて、サポートされているすべてのメソッドをすぐに利用できるようにすることです。このアプローチの利点は最大の欠点でもあります。一度公開されると、これらのメソッドはすべて API の一部になってしまいます。ほとんどの場合、後から何かを追加するよりも、何かを取り除く方が困難です。さらに、ストアの詳細を使用すると、ストアがドメインに漏洩します。パフォーマンスの観点からは、ペナルティはありません。

上記のムービーエンティティのいずれかに適合するリアクティブリポジトリは次のようになります。

MovieRepository.java
import reactor.core.publisher.Mono;

import org.springframework.data.neo4j.repository.ReactiveNeo4jRepository;

public interface MovieRepository extends ReactiveNeo4jRepository<MovieEntity, String> {

	Mono<MovieEntity> findOneByTitle(String title);
}
リアクティブコードのテストは reactor.test.StepVerifier を使用して行われます。プロジェクト Reactor の対応するドキュメント (英語) を参照するか、サンプルコードを参照してください。