このバージョンはまだ開発中であり、まだ安定しているとは見なされていません。最新の安定バージョンについては、Spring Data Neo4j 7.5.1 を使用してください! |
Spring Data Neo4j 射影
上で記述されていたように、射影には、インターフェースと DTO ベースの射影という 2 つの種類があります。Spring Data Neo4j では、両方の型の射影が、どのプロパティと関連がワイヤ上で転送されるかに直接影響します。アプリケーションのすべての使用シナリオで必要ではない可能性のある多くのプロパティを含むノードとエンティティを扱う場合、どちらのアプローチでもデータベースの負荷を軽減できます。
インターフェースと DTO ベースの射影の両方で、Spring Data Neo4j はクエリの構築にリポジトリのドメイン型を使用します。クエリを変更する可能性のあるすべての属性のすべてのアノテーションが考慮されます。ドメイン型は、リポジトリ宣言によって定義された型です ( interface TestRepository extends CrudRepository<TestEntity, Long>
のような宣言がある場合、ドメイン型は TestEntity
になります)。
インターフェースベースの射影は常に、基礎となるドメイン型に対する動的プロキシになります。このようなインターフェース ( getName
など) で定義されたアクセサーの名前は、射影されたエンティティに存在するプロパティ (ここでは name
) に解決される必要があります。共通の Spring Data インフラストラクチャを通じてアクセスできる限り、これらのプロパティにドメイン型にアクセサーがあるかどうかは関係ありません。後者は、そもそもドメイン型が永続的なエンティティではないため、すでに保証されています。
DTO ベースの射影は、カスタムクエリで使用すると多少柔軟性が高くなります。標準クエリは元のドメイン型から派生しているため、そこで定義されているプロパティと関連のみを使用できますが、カスタムクエリは追加のプロパティを追加できます。
ルールは次のとおりです。まず、ドメイン型のプロパティを使用して DTO を設定します。DTO がアクセサーまたはフィールドを介して追加のプロパティを宣言した場合、Spring Data Neo4j は結果のレコード内で一致するプロパティを探します。プロパティは名前が正確に一致する必要があり、単純な型 ( org.springframework.data.neo4j.core.convert.Neo4jSimpleTypes
で定義されている) または既知の永続エンティティのいずれかにすることができます。これらのコレクションはサポートされていますが、マップはサポートされていません。
マルチレベル射影
Spring Data Neo4j はマルチレベル射影もサポートしています。
interface ProjectionWithNestedProjection {
String getName();
List<Subprojection1> getLevel1();
interface Subprojection1 {
String getName();
List<Subprojection2> getLevel2();
}
interface Subprojection2 {
String getName();
}
}
循環射影をモデル化したり、循環を作成するエンティティを指定したりすることは可能ですが、射影ロジックはそれらの循環には従わず、循環のないクエリを作成するだけです。
マルチレベル射影は、射影すべきエンティティに限定されます。この場合、RelationshipProperties
はエンティティのカテゴリに分類され、射影が適用される場合は考慮される必要があります。
射影のデータ操作
射影を DTO としてフェッチした場合は、その値を変更できます。ただし、インターフェースベースの射影を使用している場合は、インターフェースを更新するだけでは済みません。使用できる一般的なパターンは、インターフェースを使用し、インターフェースからコピーされた値を使用してドメインエンティティを作成するメソッドをドメインエンティティクラスに提供することです。このようにして、次のセクションで説明するように、エンティティを更新し、射影ブループリント / マスクを使用してエンティティを再度永続化できます。
射影の永続性
射影によるデータの取得と同様に、永続化の青写真としても使用できます。Neo4jTemplate
は、これらの射影を保存操作に適用するための流れるような API を提供します。
特定のドメインクラスの射影を保存することもできます
Projection projection = neo4jTemplate.save(DomainClass.class).one(projectionValue);
または、ドメインオブジェクトを保存しても、射影で定義されたフィールドのみを考慮することもできます。
Projection projection = neo4jTemplate.saveAs(domainObject, Projection.class);
どちらの場合も、コレクションベースの操作にも使用でき、射影で定義されたフィールドとリレーションシップのみが更新されます。
データの削除 (関連の削除など) を防ぐために、後で永続化する必要がある少なくともすべてのデータを常にロードする必要があります。 |
完全な例
次のエンティティ、射影、対応するリポジトリがあるとします。
@Node
class TestEntity {
@Id @GeneratedValue private Long id;
private String name;
@Property("a_property") (1)
private String aProperty;
}
1 | このプロパティはグラフ内では異なる名前になっています |
TestEntity
から継承する派生エンティティ @Node
class ExtendedTestEntity extends TestEntity {
private String otherAttribute;
}
TestEntity
の界面突起 interface TestEntityInterfaceProjection {
String getName();
}
TestEntity
の DTO 射影 (1 つの追加属性を含む)class TestEntityDTOProjection {
private String name;
private Long numberOfRelations; (1)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Long getNumberOfRelations() {
return numberOfRelations;
}
public void setNumberOfRelations(Long numberOfRelations) {
this.numberOfRelations = numberOfRelations;
}
}
1 | この属性は投影されたエンティティに存在しません |
TestEntity
のリポジトリは以下に示されており、リストで説明したように動作します。
TestEntity
のリポジトリ interface TestRepository extends CrudRepository<TestEntity, Long> { (1)
List<TestEntity> findAll(); (2)
List<ExtendedTestEntity> findAllExtendedEntities(); (3)
List<TestEntityInterfaceProjection> findAllInterfaceProjectionsBy(); (4)
List<TestEntityDTOProjection> findAllDTOProjectionsBy(); (5)
@Query("MATCH (t:TestEntity) - [r:RELATED_TO] -> () RETURN t, COUNT(r) AS numberOfRelations") (6)
List<TestEntityDTOProjection> findAllDTOProjectionsWithCustomQuery();
}
1 | リポジトリのドメイン型は TestEntity です |
2 | 1 つ以上の TestEntity を返すメソッドは、ドメイン型に一致するため、そのインスタンスのみを返します。 |
3 | ドメイン型を継承するクラスの 1 つ以上のインスタンスを返すメソッドは、拡張したクラスのインスタンスのみを返します。問題のメソッドのドメイン型は、リポジトリ自体のドメイン型を満たす拡張クラスになります。 |
4 | このメソッドはインターフェース射影を返すため、メソッドの戻り値の型はリポジトリのドメインの型とは異なります。インターフェースは、ドメイン型で定義されたプロパティにのみアクセスできます。サフィックス By は、SDN が TestEntity で InterfaceProjections というプロパティを検索しないようにするために必要です。 |
5 | このメソッドは DTO 射影を返します。これを実行すると、DTO がドメイン型の契約にない追加属性として numberOfRelations を定義しているため、SDN が警告を発行します。TestEntity 内のアノテーション付き属性 aProperty は、クエリ内で a_property に正しく変換されます。上記のように、戻り値の型はリポジトリのドメインの型とは異なります。サフィックス By は、SDN が TestEntity 内の DTOProjections というプロパティを検索しないようにするために必要です。 |
6 | このメソッドは DTO 射影も返します。ただし、クエリには射影で定義された追加属性に適合する値が含まれているため、警告は発行されません。 |
上記のリストのリポジトリでは、具体的な戻り値の型を使用して射影を定義していますが、別のバリエーションとして、Spring Data Neo4j が他の Spring Data プロジェクトと共有するドキュメントの一部で説明されている動的射影の使用があります。動的射影は、クローズドインターフェース射影とオープンインターフェース射影の両方に適用できるほか、クラスベースの DTO 射影にも適用できます。 動的射影の鍵は、 <T> Collection<T> findByName(String name, Class<T> type) のように、リポジトリ内のクエリメソッドへの最後のパラメーターとして目的の射影型を指定することです。これは、上記の TestRepository に追加できる宣言で、複数のメソッドで可能な @Query アノテーションを繰り返すことなく、同じメソッドで取得されるさまざまな射影を可能にします。 |