тайм-аут весенней транзакции не работает - PullRequest
0 голосов
/ 06 сентября 2011

Я пытаюсь остановить / откатить транзакцию, если она выполняется слишком долго.Но, похоже, это не сработает, настроив атрибут timeout менеджера транзакций Spring.Мое окружение:

  1. весна 2.5.6 + JPA + спящий режим 3.2.6
  2. оракул 10g
  3. jdk 1.6.0_17

Поскольку 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){}
    }
}

Также я изменяю пружинный 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 запустит таймер при запуске новой транзакции, если таймер достигнет ограничения по времени, он откатит транзакцию.Не могли бы вы сказать мне, почему ???

Обновлено >>

При просмотре учебного руководства по JavaEE7 обнаружил, что, кажется, JPA2.1 предоставил поддержку времени ожидания блокировки (в общем случае время ожидания транзакциивызвано таймаутом получения блокировки).

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

42.2.2.1 Тайм-ауты пессимистической блокировки

Ответы [ 2 ]

1 голос
/ 07 сентября 2011
0 голосов
/ 10 апреля 2012

После некоторых исследований я обнаружил, что проблема заключается в потоке TimerTask, который не использует пружинные прокси, которые обычно запускают и фиксируют транзакции. Теоретически, вы можете вручную добавить поддержку TimerTask для работы с прокси, но для меня это очень хлопотно.

У Spring есть своя собственная структура планирования, которую вы можете использовать вместо TimerTask для выполнения runnables, и для ее использования не потребуется большого изменения кода.

Вот документы:

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...