Поскольку мы не можем присвоить значение переменной атрибуту аннотации Java, для программной установки @Transactional
timeout
лучше всего переопределить AbstractPlatformTransactionManager#determineTimeout()
.
Предположим, вы используете JpaTransactionManager
, новый менеджер выглядит как код ниже. Это позволяет установить таймаут для каждой транзакции. Мы можем использовать имя TransactionDefinition
для идентификации транзакции, которая в случае декларативной транзакции Spring имеет имя по умолчанию в формате FullyQualifiedClassName.MethodName
.
public class FooTransactionManager extends JpaTransactionManager {
private Map<String, Integer> txTimeout = new HashMap<String, Integer>();
public <T> void configureTxTimeout(Class<T> clazz, String methodName, Integer timeoutSecond) {
txTimeout.put(clazz.getName() + "." + methodName, timeoutSecond);
}
//The timeout set by `configureTxTimeout` will have higher priority than the one set in @Transactional
@Override
protected int determineTimeout(TransactionDefinition definition) {;
if (txTimeout.containsKey(definition.getName())) {
return txTimeout.get(definition.getName());
} else {
return super.determineTimeout(definition);
}
}
}
Затем настройте PlatformTransactionManager
:
@Bean
public PlatformTransactionManager transactionManager(final EntityManagerFactory emf) {
final FooTransactionManager transactionManager = new FooTransactionManager();
transactionManager.setEntityManagerFactory(emf);
transactionManager.configureTxTimeout(Foo.class, "doStuff", 10);
transactionManager.configureTxTimeout(Bar.class, "doStuff", 20);
transactionManager.configureTxTimeout(Bar.class, "doMoreStuff", 30);
//blablabla
return transactionManager;
}
Приведенные выше коды предназначены только для демонстрации. В действительности вы можете использовать @Value
для чтения значения из внешних свойств (например, application.yml
) во время конфигурации.