Springboot+Mybatis+Druid动态数据源切换启用声明式事务后切换失败的解决方式

当使用SpringBoot、Mybatis和Druid进行多数据源动态切换并启用声明式事务时,遇到事务切换失败的问题。解决办法是重写事务管理器,包括实现Transaction接口以定制事务开启和关闭,继承SpringManagedTransactionFactory来定制事务工厂,以及配置Springboot的事务管理、Session管理、Mybatis配置和yml文件。通过这些步骤,可以成功解决在事务中切换数据源失败的难题。
摘要由CSDN通过智能技术生成

事务切换失败是因为不在同一事务下,所以需要重写事务管理器
关于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(
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值