変更するデータの書き込みロックを安全に行うためのすばらしい作業です。:)しかし、あなたは船外に出る/それを長い道のりでやっているかもしれません。
最初にマイナーな点。persist()の呼び出しは必要ありません。更新するには、find()から返されたエンティティの属性を変更するだけです。entityManagerは変更を自動的に認識し、コミット中にそれらをデータベースに書き込みます。Persistが必要になるのは、新しいオブジェクトを作成してそれを初めてデータベースに書き込む場合(または、新しい子オブジェクトを親リレーションに追加し、cascade = PERSISTを介して永続をカスケードする場合)です。
ほとんどのアプリケーションでは、独自の個別のトランザクションと個別の永続コンテキストを持つ異なるスレッドによる同じデータへの同時更新が「衝突」する可能性が低くなります。これが当てはまり、スケーラビリティを最大化したい場合は、悲観的な読み取りまたは書き込みロックではなく、楽観的な書き込みロックを使用してください。これは、大多数のWebアプリケーションに当てはまります。まったく同じデータ整合性、はるかに優れたパフォーマンス/スケーラビリティを提供しますが、(まれに)OptimisticLockExceptionを処理する必要があります。
楽観的な書き込みロックは、dbとエンティティにshort / integer / long / TimeStamp属性を設定し、エンティティに@Versionアノテーションを付けるだけで自動的に組み込まれます。その場合、entityManager.lock()を呼び出す必要はありません。
上記に満足し、エンティティに@Version属性を追加した場合、コードは次のようになります。
try {
entityManager.getTransaction().begin();
r = entityManager.find(Route.class, r.getPrimaryKey());
r.setRoute(txtRoute.getText());
entityManager.getTransaction().commit();
} catch (OptimisticLockException e) {
// Logging and (maybe) some error handling here.
// In your case you are lucky - you could simply rerun the whole method.
// Although often automatic recovery is difficult and possibly dangerous/undesirable
// in which case we need to report the error back to the user for manual recovery
}
つまり、明示的なロックはまったくありません。エンティティマネージャはそれを自動的に処理します。
同時データ更新の「衝突」を回避する必要が強く、スケーラビリティが制限されたコードを使用できる場合は、悲観的な書き込みロックを介してデータアクセスをシリアル化します。
try {
entityManager.getTransaction().begin();
r = entityManager.find(Route.class, r.getPrimaryKey(), LockModeType.PESSIMISTIC_WRITE);
r.setRoute(txtRoute.getText());
entityManager.getTransaction().commit();
} catch (PessimisticLockException e) {
// log & rethrow
}
どちらの場合も、コミットの成功または自動ロールバックの例外は、実行されたロックが自動的にクリアされることを意味します。
乾杯。