我試圖停止/回滾一個交易,如果它運行時間過長。但是,通過配置spring的事務管理器的超時屬性似乎不起作用。 我的環境:春季交易超時不起作用
- 春天2.5.6 + JPA +休眠3.2.6
- 的Oracle 10g
- 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悲觀鎖定超時
能否請您澄清誰調用的TimerTask(哪個班)?此外,有關如何使用自定義或彈簧調度來解決此問題的任何提示? @Ramon,你能告訴我什麼是解決方案嗎? –