2015-01-08 12 views
7
@Transactional (noRollbackFor=RuntimeException.class) 
public void methodA (Entity e){ 
    service.methodB(e); 
} 

をロールバックすることを妨げない---以下、サービス方法---@Transactional(noRollbackFor = RuntimeException.class)のRuntimeException

@Transactional (propagation=Propagation.REQUIRES_NEW, noRollbackFor=RuntimeException.class) 
public void methodB (Entity e){ 
    dao.insert(e); 
} 

methodB()dao.insert(e)主キー違反が発生し、ConstraintViolationExceptionをスローこれはRuntimeExceptionのサブクラスですが、私が使用したnoRollbackForというプロパティのためにトランザクションがコミットされると思います。それがロールバック専用としてマークされているので、 トランザクションがロールバック:しかし、私は(methodA上の)外側のトランザクションがまだメッセージ

org.springframework.transaction.UnexpectedRollback例外でHibernateTransactionManagerによってロールバックされていることを観察しました

同様の質問が報告されていますが、これは正確ではありません。例外がキャッチされると

+1

はあなたが偽例えばにglobalRollbackOnParticipationFailureを設定しました:emailServiceはSendMailFailureExceptionをスローした場合、あなたはそれがこの例外をキャッチする際にロールバックすることはないGatewayServiceのを指示することができます。 <プロパティ名= "sessionFactory" ref = "sessionFactory" sol4me

+0

確かにsol4meは正しい軌道にあります - http://stackoverflow.com/a/11205537/1594449を参照してください。 – gknicker

+0

私は素晴らしいアイディアのようですが、私は 'globalRollbackOnParticipationFailure'の設定を変更したくはありません。すでに同じトランザクションマネージャを使用している既存のモノリシックなコードを強化しています。既存のコードを自分の変更に影響されないようにしたいと思っています。これはtxマネージャの設定を変更することによって実現可能には見えません。 変更に固有の何かを行うことはできますか? – ThermalEagle

答えて

9

Hibernate Sessionは破棄されなければならないとトランザクションはロールバックする必要があります。

セッションが例外をスローした場合、トランザクションは バックやセッション破棄を巻いておく必要があります。セッション の内部状態は、例外が発生した後でデータベースと一致しない可能性があります。

したがって、noRollbackForは、例外をスローするサービスとDAOレイヤーに適用されます。 gatewayServiceがHibernate DAOを介してデータベースに書き込みを行い、emailServiceを介して電子メールを送信しているとします。

@Transactional(noRollbackFor=SendMailFailureException.class) 
public void saveAndSend(Entity e){ 
    dao.save(e); 
    emailService.send(new Email(e)); 
} 
+0

まあ例で私の理解が何であるか –

+0

@AndyDufresne説明 - ように'メソッドB'は独自のトランザクションを持っているが、この方法トランザクションは、中断されますプロキシ、プロキシは 'ターゲットメソッドメソッドB 'と呼ばれ、'ロールバックなし'が設定されている例外が発生した場合、このトランザクションだけが処理され、 'メソッドA 'のトランザクションを再開する。 –

+0

Propagation.REQUIRES_NEWのために新しいトランザクション、Hibernate Sessionにも同じ原則が適用されます。 –