このバージョンはまだ開発中であり、まだ安定しているとは見なされていません。最新の安定バージョンについては、Spring Data Neo4j 7.4.4 を使用してください! |
一意の ID の処理とプロビジョニング
Neo4j 内部 ID の使用
ドメインクラスに一意の識別子を与える最も簡単なメソッドは、型 String
または Long
のフィールドで @Id
と @GeneratedValue
を組み合わせることです (インスタンスが新しいかどうかを示すより適切な指標はリテラル null
であるため、スカラー long
ではなくオブジェクトが望ましい) ):
@Node("Movie")
public class MovieEntity {
@Id @GeneratedValue
private Long id;
private String name;
public MovieEntity(String name) {
this.name = name;
}
}
フィールドに setter を指定する必要はありません。SDN はリフレクションを使用してフィールドを割り当てますが、setter がある場合はそれを使用します。内部生成された ID を使用して不変のエンティティを作成したい場合は、wither を指定する必要があります。
@Node("Movie")
public class MovieEntity {
@Id @GeneratedValue
private final Long id; (1)
private String name;
public MovieEntity(String name) { (2)
this(null, name);
}
private MovieEntity(Long id, String name) { (3)
this.id = id;
this.name = name;
}
public MovieEntity withId(Long id) { (4)
if (this.id.equals(id)) {
return this;
} else {
return new MovieEntity(id, this.title);
}
}
}
1 | 生成された値を示す不変の最終 ID フィールド |
2 | アプリケーションと Spring Data によって使用されるパブリックコンストラクター |
3 | 内部で使用されるコンストラクター |
4 | id -attribute のいわゆる枯れです。元のエンティティを変更せずに、新しいエンティティを作成し、それに応じてフィールドを設定することで、エンティティを不変にします。 |
必要な場合は、id 属性に setter を指定するか、wither のようなものを指定する必要があります。
利点: id 属性が代理ビジネスキーであることは明らかであり、それを使用するためにそれ以上の努力や構成は必要ありません。
不利益: これは Neo4js 内部データベース ID に関連付けられていますが、これはデータベースの存続期間全体にわたってのみアプリケーションエンティティに固有のものではありません。
不利益: 不変エンティティを作成するにはより多くの労力が必要です
外部から提供された代理キーを使用する
@GeneratedValue
アノテーションは、org.springframework.data.neo4j.core.schema.IdGenerator
を実装するクラスをパラメーターとして受け取ることができます。SDN は、すぐに使用できる InternalIdGenerator
(デフォルト) および UUIDStringGenerator
を提供します。後者は、エンティティごとに新しい UUID を生成し、java.lang.String
として返します。これを使用するアプリケーションエンティティは次のようになります。
@Node("Movie")
public class MovieEntity {
@Id @GeneratedValue(UUIDStringGenerator.class)
private String id;
private String name;
}
利点と欠点に関しては、2 つのことを別々に議論する必要があります。割り当て自体と UUID 戦略。普遍的に一意の識別子 [Wikipedia] (英語) は、実用的な目的のために一意であることを目的としています。Wikipedia の言葉を引用すると、「したがって、誰でも UUID を作成し、それを使用して何かを識別することができます。その識別子は、他のものを識別するためにすでに作成された、または今後作成される識別子とほぼ確実に重複しません。」私たちの戦略は Java 内部 UUID メカニズムを使用し、暗号的に強力な擬似乱数ジェネレーターを採用します。ほとんどの場合、これで問題なく動作するはずですが、実際の実行距離は異なる場合があります。
これで割り当て自体は残ります。
アドバンテージ: アプリケーションは完全に制御しており、アプリケーションの目的に十分な一意のキーを生成できます。生成された値は安定しているため、後で変更する必要はありません。
不利益: 生成された戦略はアプリケーション側に適用されます。当時、ほとんどのアプリケーションは適切に拡張するために複数のインスタンスにデプロイされます。戦略が重複を生成する傾向がある場合、主キーの一意性プロパティが違反されるため、挿入は失敗します。このシナリオでは一意のビジネスキーについて考える必要はありませんが、何を生成するかについてはさらに考える必要があります。
独自の ID ジェネレーターを展開するには、いくつかのオプションがあります。1 つはジェネレーターを実装する POJO です。
import java.util.concurrent.atomic.AtomicInteger;
import org.springframework.data.neo4j.core.schema.IdGenerator;
import org.springframework.util.StringUtils;
public class TestSequenceGenerator implements IdGenerator<String> {
private final AtomicInteger sequence = new AtomicInteger(0);
@Override
public String generateId(String primaryLabel, Object entity) {
return StringUtils.uncapitalize(primaryLabel) +
"-" + sequence.incrementAndGet();
}
}
別のオプションは、次のように追加の Spring Bean を提供することです。
@Component
class MyIdGenerator implements IdGenerator<String> {
private final Neo4jClient neo4jClient;
public MyIdGenerator(Neo4jClient neo4jClient) {
this.neo4jClient = neo4jClient;
}
@Override
public String generateId(String primaryLabel, Object entity) {
return neo4jClient.query("YOUR CYPHER QUERY FOR THE NEXT ID") (1)
.fetchAs(String.class).one().get();
}
}
1 | 必要なクエリまたはロジックを正確に使用してください。 |
上記のジェネレーターは、次のように Bean リファレンスとして構成されます。
@Node("Movie")
public class MovieEntity {
@Id @GeneratedValue(generatorRef = "myIdGenerator")
private String id;
private String name;
}
ビジネスキーの使用
完全な例の MovieEntity
および PersonEntity
ではビジネスキーを使用しています。個人の名前は、アプリケーションによって、および Spring Data を介してロードされる際の両方で、構築時に割り当てられます。
これは安定した一意のビジネスキーを見つけた場合にのみ可能ですが、優れた不変ドメインオブジェクトが作成されます。
利点: ビジネスキーまたは自然キーを主キーとして使用するのは自然なことです。問題のエンティティは明確に識別されており、ドメインをさらにモデル化する際に、ほとんどの場合、それが適切であると感じられます。
短所: 見つかったキーが思ったほど安定していないことがわかると、主キーとしてのビジネスキーを更新するのは難しくなります。たとえそうでないと約束したとしても、変更される可能性があることが判明することはよくあります。それとは別に、あるものにとって本当に一意な識別子を見つけるのは困難です。
ビジネスキーは、Spring Data Neo4j が処理する前に常にドメインエンティティに設定されることに注意してください。これは、@Version
フィールドも提供されない限り、エンティティが新しいかどうかを判断できないことを意味します (エンティティは常に新しいと想定されます)。