У меня есть кодовая база, которая используется для двух разных приложений. некоторые из моих весенних классов обслуживания имеют аннотацию @Transactional. При запуске сервера я хотел бы отключить @Transactional на основе некоторой конфигурации.
Ниже приведен мой класс конфигурации.
@Configuration
@EnableTransactionManagement
@PropertySource("classpath:application.properties")
public class WebAppConfig {
private static final String PROPERTY_NAME_DATABASE_DRIVER = "db.driver";
@Resource
private Environment env;
@Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(env.getRequiredProperty(PROPERTY_NAME_DATABASE_DRIVER));
dataSource.setUrl(url);
dataSource.setUsername(userId);
dataSource.setPassword(password);
return dataSource;
}
@Bean
public PlatformTransactionManager txManager() {
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
def.setIsolationLevel(TransactionDefinition.ISOLATION_DEFAULT);
if (appName.equqls("ABC")) {
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_NEVER);
}else {
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
}
CustomDataSourceTransactionManager txM=new CustomDataSourceTransactionManager(def);
txM.setDataSource(dataSource());
return txM;
}
@Bean
public JdbcTemplate jdbcTemplate() {
JdbcTemplate jdbcTemplate = new JdbcTemplate();
jdbcTemplate.setDataSource(dataSource());
return jdbcTemplate;
}
}
Я пытаюсь использовать методы в DataSourceTransactionManager, чтобы обеспечить функциональность. Но все же он пытается зафиксировать/откатить транзакцию в конце транзакции. Поскольку нет доступного подключения к базе данных, возникает исключение.
Если я сохраняю @Transactional(propagation=Propagation.NEVER), все работает отлично, но я не могу изменить его, так как другое приложение использует ту же кодовую базу, и в этом случае это необходимо.
Я хотел бы знать, есть ли возможность полностью отключить транзакцию из конфигурации без изменения аннотации @Transactional.
Я не уверен, что это сработает, но вы можете попробовать реализовать пользовательский TransactionInterceptor
и переопределить его метод, который превращает вызов в транзакцию, удалив этот транзакционный материал. Что-то вроде этого:
public class NoOpTransactionInterceptor extends TransactionInterceptor {
@Override
protected Object invokeWithinTransaction(
Method method,
Class<?> targetClass,
InvocationCallback invocation
) throws Throwable {
// Simply invoke the original unwrapped code
return invocation.proceedWithInvocation();
}
}
Затем вы объявляете условный компонент в одном из @Configuration
классов.
// assuming this property is stored in Spring application properties file
@ConditionalOnProperty(name = "turnOffTransactions", havingValue = "true"))
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionInterceptor transactionInterceptor(
/* default bean would be injected here */
TransactionAttributeSource transactionAttributeSource
) {
TransactionInterceptor interceptor = new NoOpTransactionInterceptor();
interceptor.setTransactionAttributeSource(transactionAttributeSource);
return interceptor;
}
Возможно, вам понадобятся дополнительные настройки, я не могу проверить это прямо сейчас.
Этот ответ очень полезен! Большое спасибо!