事务切换失败是因为不在同一事务下,所以需要重写事务管理器
关于Druid多数据源的配置方式请参考另外一篇博文:
https://blog.csdn.net/kugeliujian/article/details/103318180
事务管理部分的代码如下:
1、实现Transaction接口重写事务开启关闭方法
package com.bsoft.core.datasource;
import org.apache.ibatis.transaction.Transaction;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.CannotGetJdbcConnectionException;
import org.springframework.jdbc.datasource.DataSourceUtils;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import static org.apache.commons.lang3.Validate.notNull;
/**
* @author :Liujian
* @date :2019/11/19 23:13
* @description:动态数据源事务管理器
* @version:
*/
public class DynamicRoutingDataSourceTransaction implements Transaction {
private static Logger logger = LoggerFactory.getLogger(DynamicRoutingDataSourceTransaction.class);
private final DataSource dataSource;
private Connection mainConnection;
private String mainDatabaseIdentification;
private ConcurrentMap<String, Connection> otherConnectionMap;
private boolean isConnectionTransactional;
private boolean autoCommit;
public DynamicRoutingDataSourceTransaction(DataSource dataSource) {
notNull(dataSource, "No DataSource specified");
this.dataSource = dataSource;
otherConnectionMap = new ConcurrentHashMap<>();
mainDatabaseIdentification = DynamicDataSourceHolder.getDataSourceRouterKey();
}
@Override
public Connection getConnection() throws SQLException {
String databaseIdentification = DynamicDataSourceHolder.getDataSourceRouterKey();
logger.info("使用数据源{}开启事务!", databaseIdentification);
if (databaseIdentification.equals(mainDatabaseIdentification)) {
if (mainConnection != null) return mainConnection;
else {
openMainConnection();
mainDatabaseIdentification = databaseIdentification;
return mainConnection;
}
} else {
if (!otherConnectionMap.containsKey(databaseIdentification)) {
try {
Connection conn = dataSource.getConnection();
otherConnectionMap.put(databaseIdentification, conn);
} catch (SQLException ex) {
throw new CannotGetJdbcConnectionException("Could not get JDBC Connection", ex);
}
}
return otherConnectionMap.get(databaseIdentification);
}
}
private void openMainConnection() throws SQLException {
this.mainConnection = DataSourceUtils.getConnection(this.dataSource);
this.autoCommit = this.mainConnection.getAutoCommit();
this.isConnectionTransactional = DataSourceUtils.isConnectionTransactional(