楽観的なトランザクションを実行するためにコントローラーで使用する TransactionService を導入しました。そうすべき
- 与えられたトランザクションを実行しようとする (= 閉鎖)
- 失敗した場合はロールバックし、
- 失敗したらもう一度試す
基本的には次のようになります。
class TransactionService {
transactional = false // Because withTransaction is used below anyway
def executeOptimisticTransaction(Closure transaction) {
def success = false
while (!success) {
anyDomainClass.withTransaction { status ->
try {
transaction()
success = true
} catch(Exception e) {
status.setRollbackOnly()
}
}
}
}
}
もう少し複雑です。たとえば、再試行する前に別の Thread.sleeps を使用し、ある段階で中止しますが、ここでは問題ではありません。クロージャーとして安全に実行されるトランザクションを渡すコントローラーから呼び出されます。
私の問題:サービスが同時更新のために org.hibernate.StaleObjectStateException にヒットすると、再試行を続けますが、例外は消えません。
コントローラーから渡されたトランザクションでドメインクラスを再アタッチしたり、サービスまたはコントローラーでセッションをクリアしたりするなど、すでにさまざまなことを試しましたが、役に立ちませんでした。私は何が欠けていますか?
status.createSavepoint() を使用して transaction() が呼び出される前に savePoint を挿入しようとすると、「Transaction Manager はネストされたトランザクションを許可しません」というエラーが発生したことに注意してください。トランザクションがコントローラーからサービスに渡されるためにエラーが存在し、それを回避するために新しい/ネストされたトランザクションを開始する必要があるのではないかと疑ったため、これを試しましたが、エラーが示すように、私の場合は不可能です。
それとも、トランザクションをクロージャーとして渡すことが問題なのでしょうか?
.withTransaction の前に使用されるドメイン クラスは問題ではないと思いますか?