以下のコードスニペットでは、AccountとAccountDetailsという2つのエンティティを永続化しようとしています。私はこれを原子的にしたい。つまり、AccountとAccountDetailsの両方のエンティティは、単一のトランザクションで永続化する必要があります。私はそれを達成することができません。1つのトランザクションで複数のテーブルにデータを永続化する
AccountDetailsテーブルは、外部キー(account.id)を持つAccountテーブルを参照しています。
私はそれらを同じトランザクションに保持しようとすると、私はデッドロックに陥ります。そうでなければ、セッションが異なる2つの異なる取引が必要です。
Account instance = (Account) transientInstance;
Set<AccountDetails> accountDetailses = instance.getAccountDetailses();
AccountsHomeFactory factory = AccountsHomeFactory.getInstance();
AccountDetailsHome accountDetailsDAO = (AccountDetailsHome) factory.getDAO("AccountDetails");
transaction.begin();
sessionFactory.getCurrentSession().persist(instance);
transaction.commit();
// get new session ands start the transaction.
transaction.begin();
for (AccountDetails accountDetails : accountDetailses) {
accountDetailsDAO.persist(accountDetails);
log.debug("persist successful");
}
log.debug("transaction commit");
transaction.commit();
質問:
- どのようにしてデッドロックを回避することができますか?デッドロックはなぜここで起こるのですか?結局のところ、論理的にはAccountDetailsは、アカウントのロックを保持する必要はありません。
セッションとトランザクションが個々のデータアクセスオブジェクトによって処理される場所を回避することができますが、私が探しているアトミック性を達成できません。 –
実際には、複数のプロセスに対して1つのセッションを使用することはできません。この戦略は、1つのプロセスに対する1つのセッションです。 JPA実装を使用することができます。私はentitymanagerfactoryとentitymanagerを意味します。多くのプロセスでentitymanagerを使用できます。しかし、セッションでは不可能だと思います。 – mbaydar
機能テーブルとその詳細テーブルのトランザクションを作成することは意味がありません。私は2つの操作を分離することは決してありません。 1回のトランザクションで複数のテーブルを変更したい場合それを行うには? –