如何解决使用路由数据源和JdbcTemplate引导多个数据库事务
我需要在两个不同的数据库之间执行事务操作。我可以找到JPA多个数据源事务的多个示例,但JdbcTemplate找不到任何示例。无论如何,我使用ChainedTransactionManager进行了一些改动,尝试了相同的方法。这是示例代码
// This gives the Datasource list in cluster 1. Similarly done for cluster 2 too.
@Bean(name = "loadCluster1Bean")
public List<DataSource> loadCluster1() {
List<DataSource> dataSources = new ArrayList<>();
try {
// Do Hikari Configs and Get the DataSources
dataSources = getDatasources()
} catch (Exception e) {
...LOG
}
return dataSources;
}
在这里,我们使用数据源列表创建datasourceTransaction Manager。
@Bean(name = "cluster1TransactionManager")
@DependsOn({"loadCluster1Bean"})
List<DataSourceTransactionManager> tm1(@Qualifier("loadCluster1Bean") List<DataSource> dataSources) {
List<DataSourceTransactionManager> dataSourceTransactionManagers = new ArrayList<>();
for (DataSource dataSource : dataSources) {
dataSourceTransactionManagers.add(new DataSourceTransactionManager(dataSource));
}
return dataSourceTransactionManagers;
}
@Bean(name = "cluster2TransactionManager")
@DependsOn({"loadCluster2Bean"})
List<DataSourceTransactionManager> tm2(@Qualifier("loadCluster2Bean") List<DataSource> dataSources) {
List<DataSourceTransactionManager> dataSourceTransactionManagers = new ArrayList<>();
for (DataSource dataSource : dataSources) {
dataSourceTransactionManagers.add(new DataSourceTransactionManager(dataSource));
}
return dataSourceTransactionManagers;
}
下面是chainedTransactionManager
@Configuration
@ComponentScan
public class TransactionManagerConfig {
@Bean(name = "chainedTransactionManager")
public ChainedTransactionManager transactionManager(
@Qualifier("cluster1TransactionManager") List<DataSourceTransactionManager> cluster1TransactionManagers,@Qualifier("cluster2TransactionManager") List<DataSourceTransactionManager> cluster2TransactionManagers) {
List<DataSourceTransactionManager> transactionManagers = new ArrayList<>();
transactionManagers.addAll(cluster1TransactionManagers);
transactionManagers.addAll(cluster2TransactionManagers);
return new ChainedTransactionManager(transactionManagers.toArray(new DataSourceTransactionManager[transactionManagers.size()]));
}
}
然后将如下所示的chainedTransactionManager添加到服务层(伪代码)
@Service
public class ServiceClass {
@Transactional(value = "chainedTransactionManager")
public void addData(data,dbName) {
for(cluster : clusters) { //Same data needs to be inserted into multiple clusters. This is where the transactional requirement comes.
DBConnectionContextHolder.setDatabaseInstance(cluster,dbName);
Dao.addData(data);
}
}
}
下面,我添加了DBConnectionContextHolder类和AbstractRoutingDataSource类。
public class DBConnectionContextHolder {
private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();
private static Set<String> enabledDatabases = new HashSet<>();
private DBConnectionContextHolder() {
}
public static boolean setDatabaseInstance(String dbName,String cluster) {}
contextHolder.set(cluster+"_"+dbName);
return true;
}
public static void setEnabledDatabases(Set<String> enabledDatabases) {
DBConnectionContextHolder.enabledDatabases = enabledDatabases;
}
public static String getDatabase() {
return contextHolder.get();
}
}
public class RoutingDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DBConnectionContextHolder.getDatabase();
}
}
private static final RoutingDataSource updatedRoutingDataSource = new RoutingDataSource();
//targetDataSource is a map which contains key: db-cluster name,value: HikariDataSource
updatedRoutingDataSource.setTargetDataSources(targetDataSources);
updatedRoutingDataSource.afterPropertiesSet();
但是当我运行代码时,它不起作用:/似乎连接没有更新到下一个群集。
org.springframework.dao.DuplicateKeyException: PreparedStatementCallback; SQL [INSERT INTO BLAH (A,B,C,D,E,F,G,H,I) VALUES (?,?,?)]; Duplicate entry 'abababab-1122233-2020-08-18 00:00:00-2020-09-30 00:00:00-1599064' for key 'idx_abcde'; nested exception is java.sql.SQLIntegrityConstraintViolationException: Duplicate entry 'abababab-1122233-2020-08-18 00:00:00-2020-09-30 00:00:00-1599064' for key 'idx_abcde'
在没有@Transactional
的情况下,它可以工作,并且数据被添加到两个群集中。但是,是的,如果一个群集发生故障,它不会回滚。
如果有人可以帮助使其达到工作状态,我将非常感激:) 谢谢。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。