私の Web アプリケーションでは、多くの場合、1 回のリクエストでエンティティをデータベースから読み取ったままにし、後で別のリクエストでエンティティを更新する必要があります。現在、私はヘルパーメソッドを持っています
protected <T> T refresh(T t) {
if (!entityManager.contains(t)) {
t = merge(t);
entityManager.refresh(t);
}
return t;
}
各メソッドは、他の何よりも先に、作業中のエンティティを更新します。エンティティが既に更新されている場合、何も起こりません。
これはうまく機能しましたが、後でこのソリューションには重大な問題があることに気付きました。エンティティがデータベースで同時に変更されている場合、への呼び出しが失敗します。merge
明らかに、 の内容がの即時呼び出しによって置き換えられることmerge
を「知る」ことはできません。t
refresh
この問題の適切な解決策は何でしょうか? これまでのところ、次のようなアイデアがありますが、完全に満足できるものはありません。
merge
andを呼び出す代わりにrefresh
、エンティティの ID を取得して呼び出すt = find(theClassOfT, t.getId());
これで問題は解決します。完全に新しいエンティティが得られますが、大きな欠点があります。クラス
T
と ID を知る必要があります。ID の取得は、すべてのエンティティの最上位のスーパー インターフェイスを持つことで実現できますが、クラスの取得には問題があります (JPA 実装はエンティティをサブクラス化する可能性があるため、呼び出すとt.getClass()
の実装固有のサブクラスが返されるのではないかと心配していT
ます)。- 長期的には ID のみを保持し、各リクエスト中にエンティティを最新に読み取ります。これは、設計の観点からはより正しいように見えますが (古いエンティティはとにかく無効な情報を保持しています)、ここでも のクラスを
T
手元に用意する必要があります。
更新:リクエスト全体でエンティティを保持している理由は、単に便宜上のためです。その間エンティティが変更されていないことを確認する必要は特にありません-とにかく、次のリクエストでエンティティを更新します。