美文网首页
多数据源@DS使用

多数据源@DS使用

作者: 随风_d6a2 | 来源:发表于2023-03-28 15:13 被阅读0次
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
        <version>2.5.4</version>
    </dependency>
    
    spring:
      datasource:
        #配置hikari连接池
        hikari:
          minimum-idle: 4
          maximum-pool-size: 16
          connection-timeout: 10000
          idle-timeout: 30000
          connection-init-sql: set names utf8mb4
        #动态数据源配置
        dynamic:
          #主数据源,默认启用
          primary: business
          datasource:
            #数据源1
            business:
              driver-class-name: com.mysql.cj.jdbc.Driver
              url: jdbc:mysql://localhost:3306/db_business?useUnicode=true&characterEncoding=utf-8
              username: ****
              password: ****
            #数据源2
            user:
              driver-class-name: com.mysql.cj.jdbc.Driver
              url: jdbc:mysql://localhost:3306/db_user?useUnicode=true&characterEncoding=utf-8
              username: ****
              password: ****
    

    1.注解添加在dao.mapper上无效
    2.注解添加到interface Service类上无效
    3.注解添加到interface Service方法上无效

    那么,此注解应该如何使用呢?

    添加@DS注解到实现类或者实现类的方法上才可以

    当注解添加到类上,意味着此类里的方法都使用此数据源;
    当注解添加到方法上时,意味着此方法上使用的数据源优先级高于其他一切配置.

    @Service
    @DS("slave")
    public class UserServiceImpl implements UserService {
    
     @Autowired
     private JdbcTemplate jdbcTemplate;
     public List<Map<String, Object>> selectAll() {
       return jdbcTemplate.queryForList("select * from user");
     }
    
     @Override
     @DS("slave_1")
     public List<Map<String, Object>> selectByCondition() {
       return jdbcTemplate.queryForList("select * from user where age >10");
     }
    }
    

    常见问题:
    1.不能使用事务,否则数据源不会切换,使用的还是是第一次加载的数据源 。删除 操作多数据源的方法或者类、接口 上的 注解 @Transactional() 即可。

    2.第一次加载的数据源之后,第二次(第三次...)操作其它数据源,如果数据源不存在,使用的还是第一次加载的数据源

    3.数据源名称最好不要包含下滑线,下滑线的数据源切换不了

    ————————————————
    如果使用事务处理方法如下:

    问题描述
    在配置多数据源项目中, service中根据@DS("**")配置实现数据库切换. 在加@Transactional事务的方法中, 调用另外一个数据源不用service的方法, 此方法会因为切换数据库失败导致执行sql错误. 示例如下

        @DS("master")
        public class TestMasterServiceImpl impl TestMasterService {
            
            @Transactional(rollbackFor = Exception.class)
            public Integer save() {
                subSave();
                // 以下调用配置「slave」库的service会报错, 找不到表
                testSlaveService.save();
                return null;
            }
            
            private Integer subSave() {
                // omit...
            }
        }
        
        @DS("slave")
        public class TestSlaveServiceImpl impl TestSlaveService {
            
            @Override
            public Integer save() {
                // omit...
            }
        }
    

    问题分析
    开启事务的同时,会从数据库连接池获取数据库连接, 在这个事务内的所有数据库操作都基于这个连接. 为使@DS生效, 必须重新获取数据库连接, 可以采取更改事务传播机制的方法实现.

    问题解决
    将代码修改如下, 两个方法设置事务传播机制为「propagation = Propagation.REQUIRES_NEW」

        @DS("master")
        public class TestMasterServiceImpl impl TestMasterService {
            
            @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
            public Integer save() {
                subSave();
                testSlaveService.save();
                return null;
            }
            
            private Integer subSave() {
                // omit...
            }
        }
        
        @DS("slave")
        public class TestSlaveServiceImpl impl TestSlaveService {
            
            @Override
            @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
            public Integer save() {
                // omit...
            }
        }
    

    拓展-传播机制
    5.1. 传播机制生效条件
    spring是使用aop来代理事务控制, 是针对于接口或类的, 所以在同一个 service 类中两个方法的调用, 传播机制是不生效的.
    5.2. 传播机制常用类型
    REQUIRED
    支持当前事务, 如果当前没有事务,则新建事务
    如果当前存在事务, 则加入当前事务, 合并成一个事务
    REQUIRES_NEW
    新建事务, 如果当前存在事务, 则把当前事务挂起
    这个方法会独立提交事务, 不受调用者的事务影响, 父级异常, 它也是正常提交

    其他想法
    多数据源的事务,也可以通过编程式事务处理。通过多个TransactionManager,一起提交,一起回滚;
    ————————————————
    版权声明:本文为CSDN博主「j734948791」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/j734948791/article/details/124420302

    相关文章

      网友评论

          本文标题:多数据源@DS使用

          本文链接:https://www.haomeiwen.com/subject/gjxxddtx.html