2011-09-06 194 views
0

我試圖停止/回滾一個交易,如果它運行時間過長。但是,通過配置spring的事務管理器的超時屬性似乎不起作用。 我的環境:春季交易超時不起作用

  1. 春天2.5.6 + JPA +休眠3.2.6
  2. 的Oracle 10g
  3. JDK 1.6.0_17

隨着春天的幫助來管理我的交易,它已經配置如下:

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> 
    <property name="entityManagerFactory" ref="entityManagerFactory" /> 
    <property name="dataSource" ref="dataSource" /> 
</bean> 

<!-- the transactional advice (what 'happens'; see the <aop:advisor/> bean 
    below) --> 
<tx:advice id="defaultTxAdvice" transaction-manager="transactionManager"> 
    <tx:attributes> 
     <!-- Keep SequenceService in a isolation transaction --> 
     <tx:method name="get*" read-only="true" /> 
     <!-- By default, A runtime exception will rollback transaction. --> 
     <tx:method name="*" timeout="10" rollback-for="ApplicationException" /> 
    </tx:attributes> 
</tx:advice> 

而且我有一個TicketService將插入一些記錄到數據庫,只是我讓它多睡15秒。

public class DefaultTicketService implements TicketService{ 
    public void sell() { 
     // checking and insert some records to underlying database 
     .... 
     // sleep to reach the transaction deadline 
     try {Thread.sleep(15 * 1000);} catch(Exception e){} 
    } 
} 

而且我修改春天的org.springframework.orm.jpa.JpaTransactionManager輸出更多的調試信息。

protected void doBegin(Object transaction, TransactionDefinition definition) { 
    ... ...   
    // Register transaction timeout. 
    int timeout = determineTimeout(definition); 
    if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) { 
     if (logger.isDebugEnabled()) { 
      logger.debug("****setTimeoutinSeconds(" + timeout 
        + " seconds) to EntityManager(" + txObject.getEntityManagerHolder() 
        + "), the transaction begin time:" 
        + new Date(System.currentTimeMillis())); 
     } 
     txObject.getEntityManagerHolder().setTimeoutInSeconds(timeout); 
    } 
    ... ... 
} 

protected void doCommit(DefaultTransactionStatus status) { 
    JpaTransactionObject txObject = (JpaTransactionObject) status.getTransaction(); 
    if (status.isDebug()) { 
     logger.debug("Committing JPA transaction on EntityManager [" 
       + txObject.getEntityManagerHolder().getEntityManager() + "]"); 
    } 
    try { 
     if (status.isDebug()) { 
      logger.debug("The deadline of entityManager(" 
        + txObject.getEntityManagerHolder().getEntityManager() + "):" 
        + txObject.getEntityManagerHolder().getDeadline() + ", and current time:" 
        + new Date(System.currentTimeMillis())); 
     } 
     EntityTransaction tx = txObject.getEntityManagerHolder().getEntityManager() 
       .getTransaction(); 
     tx.commit(); 
    ... ... 
} 

運行測試結束後,結果超出我的預期,交易最後承諾。下面是測試的輸出:

[JpaTransactionManager] Opened new EntityManager [[email protected]] for JPA transaction 
[JpaTransactionManager] ****[Begin]timeout:10 seconds,The deadline of entityManager([email protected]):null, and current time:Tue Sep 06 15:05:42 CST 2011 
[JpaTransactionManager] Exposing JPA transaction as JDBC transaction [SimpleConnectionHandle: [email protected]] 
[JpaTransactionManager] Found thread-bound EntityManager [[email protected]] for JPA transaction 
... ... 
[JpaTransactionManager] Initiating transaction commit 
[JpaTransactionManager] Committing JPA transaction on EntityManager [[email protected]] 
[JpaTransactionManager] ****[Commit]The deadline of entityManager([email protected]):Tue Sep 06 15:05:52 CST 2011, and current time:Tue Sep 06 15:05:58 CST 2011 
[JpaTransactionManager] Closing JPA EntityManager [[email protected]] after transaction 
[EntityManagerFactoryUtils] Closing JPA EntityManager 

從調試信息,很明顯,當前時間已超過期限,那麼爲什麼春天開不回滾事務?在我的理解中,如果我設置了超時時間(如10秒),Spring將在啓動新事務時啓動Timer,如果計時器達到時間限制,它將回滾事務。你能告訴我爲什麼?

更新>>

當通過JavaEE7,發現的教程,似乎JPA2.1提供了鎖定超時支持去(一般事務超時通過獲得鎖的超時所致)。

http://docs.oracle.com/javaee/7/tutorial/doc/persistence-locking002.htm

42.2.2.1悲觀鎖定超時

回答

0

經過一番研究,我發現,問題出在TimerTask的線程沒有使用彈簧代理通常會啓動並提交事務。從理論上講,你可以手動編寫支持到你的TimerTask中來處理代理,但這對我來說似乎很麻煩。

春天有它自己的調度框架,你可以改用的TimerTask的執行可運行,並且不需要太多的代碼改變改用。

這裏的文檔:

http://static.springsource.org/spring/docs/3.0.5.RELEASE/reference/scheduling.html

+0

能否請您澄清誰調用的TimerTask(哪個班)?此外,有關如何使用自定義或彈簧調度來解決此問題的任何提示? @Ramon,你能告訴我什麼是解決方案嗎? –