入門
SDN 用に Spring Boot スターターを提供します。依存関係管理を介してスターターモジュールを含め、使用するボルト URL ( spring.neo4j.uri=bolt://localhost:7687
など) を構成してください。スターターは、サーバーが認証を無効にしていると想定します。SDN スターターは Java ドライバーのスターターに依存するため、そこに記載されている設定に関するすべての内容がここにも当てはまります。使用可能なプロパティのリファレンスについては、spring.neo4j
名前空間の IDE の自動補完を使用してください。
SDN のサポート
よく知られ理解されている命令型プログラミングモデル (Spring Data JDBC や JPA によく似ています)
リアクティブトランザクション (英語) の完全サポートを含む、Reactive Streams (英語) に基づくリアクティブプログラミング。
これらはすべて同じバイナリに含まれています。リアクティブプログラミングモデルでは、データベース側に 4 つ以上の Neo4j サーバーが必要で、一方でリアクティブ Spring が必要です。
データベースを準備する
この例では、すべての Neo4j インスタンスにフリーで付属しているため、ムービーグラフ (英語) 内に留まります。
実行中のデータベースはないが、Docker がインストールされている場合は、次を実行してください。
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 プロジェクトを作成できます。
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
に手動で追加する必要があります。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-neo4j</artifactId>
</dependency>
既存のプロジェクトの場合は、依存関係を手動で追加することもできます。
Gradle の使用
考え方は同じで、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
に追加する必要があります。
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 を定義することで変更できます。
@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
は次のとおりです。
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)
}
1 | Spring Data Neo4j は Spring Data Commons とそのリフレクティブ機能を使用するため、少なくともドメインパッケージを spring.core に開く必要があります。 |
2 | ここでは、your.domain にはリポジトリも含まれていると仮定します。これらは、spring.beans 、spring.context 、spring.data.commons からアクセスできるようにエクスポートする必要があります。世界にエクスポートしたくない場合は、それらのモジュールに制限できます。 |
ドメインを作成する
ドメイン層は次の 2 つのことを達成する必要があります。
グラフをオブジェクトにマッピングする
それらへのアクセスを提供する
ノードエンティティの例
SDN は、Kotlin の Java クラスと data
クラスの両方で、変更不可能なエンティティを完全にサポートします。ここでは不変エンティティに焦点を当てます。MovieEntity.java はそのようなエンティティを示します。
SDN は、Neo4j Java ドライバーがサポートするすべてのデータ型をサポートします。「Cypher 型システム」の章内の Neo4j 型をネイティブ言語型にマッピングする (英語) を参照してください。将来のバージョンでは追加のコンバーターがサポートされる予定です。 |
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 とともに使用する同じエンティティを次に示します。
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 に設定します。 |
2 | id -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 の一部になってしまいます。ほとんどの場合、後から何かを追加するよりも、何かを取り除く方が困難です。さらに、ストアの詳細を使用すると、ストアがドメインに漏洩します。パフォーマンスの観点からは、ペナルティはありません。
上記のムービーエンティティのいずれかに適合するリアクティブリポジトリは次のようになります。
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 の対応するドキュメント (英語) を参照するか、サンプルコードを参照してください。 |