_@Transactional (noRollbackFor=RuntimeException.class)
public void methodA (Entity e){
service.methodB(e);
}
_
---以下のサービス方法---
_@Transactional (propagation=Propagation.REQUIRES_NEW, noRollbackFor=RuntimeException.class)
public void methodB (Entity e){
dao.insert(e);
}
_
dao.insert(e)
のmethodB()
が主キー違反を引き起こし、ConstraintViolationException
のサブクラスであるRuntimeException
をスローした場合、トランザクションは引き続き実行されると思います。使用したnoRollbackFor
プロパティのためにコミットします。しかし、(methodA
上の)外部トランザクションがまだHibernateTransactionManager
によってメッセージとともにロールバックされていることを確認しました。
org.springframework.transaction.UnexpectedRollback例外:トランザクションはロールバックのみとしてマークされているため、ロールバックされました
同様の質問が報告されているのを見つけましたが、これは正確ではありません。
例外がキャッチされたら、 Hibernate Session を破棄し、トランザクションをロールバックする必要があります。
セッションが例外をスローした場合、トランザクションをロールバックしてセッションを破棄する必要があります。例外が発生した後、セッションの内部状態がデータベースと一致しない場合があります。
したがって、noRollbackFor
は、例外をスローする可能性のあるサービスレイヤーとDAOレイヤーに適用されます。 Hibernate DAOを介してデータベースに書き込み、emailServiceを介して電子メールを送信するgatewayServiceがあるとします。 emailServiceがSendMailFailureException
をスローした場合、この例外をキャッチしたときにロールバックしないようにgatewayServiceに指示できます。
@Transactional(noRollbackFor=SendMailFailureException.class)
public void saveAndSend(Entity e){
dao.save(e);
emailService.send(new Email(e));
}