[英]spring transaction timeout doesn't work
我试图停止/回滚事务,如果它运行时间太长。 但是通过配置spring的事务管理器的timeout属性似乎不起作用。 我的环境:
由于spring有助于管理我的交易,因此其配置如下:
<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){}
}
}
我还修改了spring的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 [org.hibernate.ejb.EntityManagerImpl@350225] for JPA transaction
[JpaTransactionManager] ****[Begin]timeout:10 seconds,The deadline of entityManager(org.hibernate.ejb.EntityManagerImpl@350225):null, and current time:Tue Sep 06 15:05:42 CST 2011
[JpaTransactionManager] Exposing JPA transaction as JDBC transaction [SimpleConnectionHandle: com.mchange.v2.c3p0.impl.NewProxyConnection@1eb41d6]
[JpaTransactionManager] Found thread-bound EntityManager [org.hibernate.ejb.EntityManagerImpl@350225] for JPA transaction
... ...
[JpaTransactionManager] Initiating transaction commit
[JpaTransactionManager] Committing JPA transaction on EntityManager [org.hibernate.ejb.EntityManagerImpl@350225]
[JpaTransactionManager] ****[Commit]The deadline of entityManager(org.hibernate.ejb.EntityManagerImpl@350225):Tue Sep 06 15:05:52 CST 2011, and current time:Tue Sep 06 15:05:58 CST 2011
[JpaTransactionManager] Closing JPA EntityManager [org.hibernate.ejb.EntityManagerImpl@350225] after transaction
[EntityManagerFactoryUtils] Closing JPA EntityManager
从调试信息中可以明显看出,当前时间已经超过了截止日期,那么为什么spring不回滚事务呢? 据我了解,如果我设置了超时时间(例如10秒),Spring将在启动新事务时启动一个Timer,如果Timer达到了时间限制,它将回滚该事务。 你能告诉我为什么吗?
更新>>
在阅读JavaEE7教程时,发现JPA2.1似乎提供了对锁超时的支持(通常事务超时是由获取锁的超时引起的)。
http://docs.oracle.com/javaee/7/tutorial/doc/persistence-locking002.htm
42.2.2.1悲观锁定超时
我发现解决方案JpaTransactionManager不支持事务超时
经过一番研究,我发现问题出在TimerTask线程上而不使用通常会启动和提交事务的Spring代理。 从理论上讲,您可以将代码支持手动编码到TimerTask中以使用代理,但这对我来说似乎很麻烦。
Spring具有自己的调度框架,您可以使用它代替TimerTask来执行可运行对象,并且不需要太多代码更改即可使用。
这是文档:
http://static.springsource.org/spring/docs/3.0.5.RELEASE/reference/scheduling.html
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.