2012-02-17 38 views
1

私はこの質問を検索しましたが、ここではStackOverflowとGoogleにかなりの数がありますが、私にとっては何もできないようです。ここSpring @Transactionはスローされた例外をロールバックしません

は私のコードは 春の設定です:(私は任意のポイントカットを使用いけない - 私は私がする必要がいけないと思いますか?)

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> 
... 
</bean> 

<bean id="hibernateSessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> 
<property name="dataSource" ref="dataSource" /> 
... 
</bean> 

<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> 
     <property name="sessionFactory" ref="hibernateSessionFactory"/> 
</bean> 
<tx:annotation-driven transaction-manager="transactionManager"/> 

私はServiceクラスを持っている:

@Service 
public class ServiceImpl implements ServiceInterface 
{ 
    /** 
    * Injected session factory 
    */ 
    @Autowired(required=true) 
    private SessionFactory sessionFactory; 

    @Autowired(required=true) 
    private Dao myDao; 

    /** 
    * {@inheritDoc} 
    */ 
    @Transactional(rollbackFor=Exception.class, propagation=Propagation.REQUIRED) 
    public void scheduleBlast(BlastParameters blastParameters) throws ServiceException 
    { 
     ... do bunch of stuff .. 
     myDao.persist(entity) 

     if(true) 
      throw new ServiceException("random error") 
    } 

    .. setter methods and other stuff .. 
} 

とダオクラス:

public class DaoImpl implements DaoInterface 
{ 
    @Autowired(required=true) 
    private SessionFactory sessionFactory 

    /** 
    * {@inheritDoc} 
    */ 
    @Transactional(propagation=Propagation.MANDATORY) 
    public void persist(Entity e) throws DaoException 
    { 
     try 
     { 
      sessionFactory.getCurrentSession().persist(e); 
     } 
     catch(Exception ex) 
     { 
      throw new DaoException(ex); 
     } 
    } 


    .. setter methods and other stuff .. 
} 

いくつかの不必要な詳細は削除されます(たとえば、セッターなどがない)。コードは完全に正常に動作します。

上記の私の問題は、スローランダム例外ラインを追加したときに、DAOを介して永続化されるオブジェクトがロールバックされないことです。

私は春3.1を使用して

思考(春3.1上にHibernate 4.0のバグがあったので)3.6休止のですか?

は、デフォルトでAutoCommitモードに設定されていたものJDBCドライバのいずれかを持っていないあなたに

+0

ブレークポイントがヒットした時点で、デバッグを試して、春が終わるところを確認してください。コードは本当に良いことですが、ソースがIDEにリンクされていることを確認してください! – davidfrancis

+0

mysqlエンジンはMyISAMまたはInnoDBを使用していますが、MyISAMはトランザクションをサポートしません。 –

+0

innoDBを使用しています。もう1つの奇妙な部分は、私が知るところです。サービスクラスは、実際にはmyDao1.persist(o1)、myDao2.persist(o2)、o1に依存するo2を持っています。 o2オブジェクトはロールバックされるが、o1オブジェクトは戻されないことがわかった。 –

答えて

10

ダオクラス @Transactional(伝播= Propagation.Mandatory、rollbackFor = {RuntimeException.class、DaoException.class})上で、次を試してみてください、私は私の問題の原因を発見し、なぜトランザクションは(一見)管理されていません正しく。私のコードのどこかに

/** 
* {@inheritDoc} 
*/ 
@Transactional(rollbackFor=Exception.class, propagation=Propagation.REQUIRED) 
public void doWork(Parameters param) throws ServiceException 
{ 
    ... do bunch of stuff .. 
    myDao1.persist(entity) 

    -- Some logic here -- 

    ... do bunch of stuff .. 
    myDao2.persist(entity2) 

    if(true) 
     throw new ServiceException("random error") 
} 

それが言う部「 - ここではいくつかのロジックが - 」、いくつかのロジックは、生のSQLを使用する行われ、アップデートの実行に呼び出しがあった:

Query query = sessionFactory.getCurrentSession().createSQLQuery(queryText); 
query.executeUpdate(); 

Hibernateクエリを使用せず、代わりに未処理のSQL実行を使用しているため、フラッシュが呼び出されたため、呼び出し前に実行された作業は と一緒にコミットされます。

私はこのロジックを考慮して、トランザクションの流れを再調整して、トランザクションが適切に管理されていることを確認します。生のSQLを使用することは、何か間違っていることを示すかもしれませんが、サービスが成し遂げようとしていることやサービスのパフォーマンスを向上させるために必要なことでした。

+0

自動または明示のいずれであっても、フラッシュはトランザクションをコミットしないでください。フラッシュは更新された/新しいエンティティのみをデータベースに送信しますが、それらは同じトランザクション内にある必要があります。@ Transactionalライフサイクルが完了するまでコミットしないでください。 –

0

をありがとうを行いますか?

+0

そんなことは考えていませんが、どこでもAUTOCOMMITの設定はありません。私のデータソースのために私は得ました:

1

@ TransactionalアノテーションをDaoImplクラスから削除してみてください。私は、トランザクション境界(DaoImpl)を越えてトランザクションがコミットされていることが起こっている可能性があると考えています。私はこのセットアップで成功した。 「内部」トランザクションに対するいくつかの異なるトランザクションアプローチを試みることができます。

もう1つは、春のトランザクションログを有効にすることです。それはそのカテゴリorg.springframework.transactionまたは何かと思います。そうすれば、ロールバックしてトランザクションをコミットすることができます。

+0

ありがとう、ダオのクラスから@Transactionalを取り除こうとしました。奇妙なことが起こっていることについての私のコメントを元のポストに見てください。基本的に私は2つの異なるオブジェクトを保持します。最初のものはコミットされ、ロールバックされません.2番目のものはロールバックされます。 –

+0

Springトランザクションログに基づいて、すべてが正確に動作するように見えます。彼らは同じセッションを使い、最初から始めました。すべての永続性は同じものを使用し、最後はロールバックします。また、両方の永続呼び出しのために "HibernateTransactionManager - 既存のトランザクションに参加する"と書かれています –

9

これはトランザクション管理の意図された動作です。 @Transactionalのデフォルトの動作は、実行時例外の場合にのみロールバックすることです。 DaoExceptionをスローした後にあなたのものをロールバックしたい場合は、それをロールバック例外リストに追加してください。 RuntimeExceptionも含めることを忘れないでください。

+0

例外はサービスクラスでスローされるため、Daoクラスの例外をキャッチすることは役に立ちません。 –

+0

次に、サービスクラスの@Transactionalアノテーション –

+0

にロールバック例外リストを追加してください。ここには素晴らしい例があります。 http://simplespringtutorial.com/springDeclarativeTransactions.html –

関連する問題