私はHibernateでEJB 3を使用しています。ステートレス セッション Bean があります。その Bean にはメソッド deleteItem があります。
クライアントが deleteItem メソッドを呼び出すと、問題なく削除が行われました。しかし、for ループを使用して deleteItem メソッドを呼び出し、そのループの制限を 5 ~ 10 回設定しようとすると、削除が失敗することがあります。しかしいつもではない。
削除操作は、実際には 2 つのテーブルからデータを削除します。子テーブルと親テーブル。各削除は、フラッシュ操作を実行することによってコミットされます。
すでに述べたように、削除を1つずつ実行しても問題は発生せず、同時に実行しようとした場合にのみ発生します。私が得ている例外は以下のとおりです
Caused by: java.sql.BatchUpdateException: Cannot delete or update a parent row: a foreign key
constraint fails (`functionTest/MotherTable`, CONSTRAINT `FKBC6CB0E6D5545EFD` FOREIGN KEY
(`MotherTable_FieldId`) REFERENCES `ChildTable` (`childTableId`))
ここで同時削除操作を行う方法はありません。また、アイテムの削除は、他のアイテムの削除操作とは関係ありません。そのため、同時実行が発生しても、複数のアイテムを同時に削除しても問題ありません。
そのため、「クライアントが複数のスレッドで同じ Bean インスタンスにアクセスしている可能性があります」という決定に至りました。このような状況では、2 つのスレッドが同じ Entity Manager State を異なる状態に保ちます。一方は永続コンテキストのフラッシュを試みますが、もう一方は子アイテムの削除をまだ完了していません。その時点で、BatchUpdateException が発生しました。- それは私の観察です。私はそれについて100%確信が持てません。
この状況を克服するために、私は楽観的ロックを採用しました。マザーテーブルにバージョン列を作成しました。今、私は OptimisticLockException を取得しています。しかし、例外をキャッチできません。以下は、OptimisticLockException をキャッチするために使用しているコードです。
private boolean deleteItem(Item itemId) {
Item item= getItem(itemId);
removeChildTableData(item);
mEm.remove(item);
try
{
mEm.flush();
}
catch (OptimisticLockException e)
{
try {
Thread.sleep(1000);
}
catch (InterruptedException e1) {
e1.printStackTrace();
}
deleteItem(itemId);
}
catch(Exception ex)
{
if (ex.getCause() instanceof OptimisticLockException)
{
try {
Thread.sleep(1000);
} catch (InterruptedException x) {
}
deleteItem(itemId);
}
}
return true;
}
したがって、私の目標は OptimisticLockException をキャッチし、削除操作を再実行することです。例外クラス名を確認しましたが、EntityNotFound です。しかし、スタック トレースで OptimisticLockException と StaleObjectStateException が発生していることがわかります。
それで、この OptimisticLockException をキャッチする方法を教えてください。