Я использую аннотации Hibernate + spring + @Transactional
для обработки транзакций в моем приложении.
Менеджер транзакций объявляется следующим образом:
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
В большинстве случаев это работает хорошо, но я обнаружил проблему, когда у меня есть 2 метода, оба аннотированных @Transactional:
package temp;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
public class OuterTestService {
@Autowired
private InnerTestService innerTestService;
@Transactional
public void outerMethod() {
try {
innerTestService.innerTestMethod();
} catch (RuntimeException e) {
// some code here
}
}
}
и
package temp;
import org.springframework.transaction.annotation.Transactional;
public class InnerTestService {
@Transactional
public void innerTestMethod() throws RuntimeException {
throw new RuntimeException();
}
}
Когда я вызываю OuterTestService # outerMethod (), я получаю исключение
org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only
Поскольку существует только одна транзакция (без вложенных транзакций), вся транзакция outerTestMethod()
помечается как только для отката.
Я обнаружил, что могу легко преодолеть это, используя noRollbackFor:
package cz.csas.pdb.be.service.tempdelete;
import org.springframework.transaction.annotation.Transactional;
public class InnerTestService {
@Transactional(noRollbackFor = RuntimeException.class)
public void innerTestMethod() throws RuntimeException {
throw new RuntimeException();
}
}
Но это должно быть явно использовано в каждом методе. Поскольку эта ошибка не возникает во время тестов (которые откатываются), это неприемлемо.
Мой вопрос - есть ли способ автоматически (например, не явно для каждого метода) установить, что транзакции откатываются только при возникновении исключения из метода, который начал транзакцию (в данном случае, outerTestMethod()
)