Spring-boot 数据源 事务 多数据源 以及 多数据源事务 问题 简单笔记

<dependency>
   <groupId>com.baomidou</groupId>
   <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
   <version>${dynamic.version}</version>
</dependency>

简介
前两篇博客介绍了用基本的方式做多数据源,可以应对一般的情况,但是遇到一些复杂的情况就需要扩展下功能了,比如:动态增减数据源、数据源分组,纯粹多库 读写分离 一主多从、从其他数据库或者配置中心读取数据源等等。其实就算没有这些需求,使用这个实现多数据源也比之前使用AbstractRoutingDataSource要便捷的多

dynamic-datasource-spring-boot-starter 是一个基于springboot的快速集成多数据源的启动器。
github: https://github.com/baomidou/dynamic-datasource-spring-boot-starter
文档: https://github.com/baomidou/dynamic-datasource-spring-boot-starter/wiki

它跟mybatis-plus是一个生态圈里的,很容易集成mybatis-plus

特性:

数据源分组,适用于多种场景 纯粹多库 读写分离 一主多从 混合模式。
内置敏感参数加密和启动初始化表结构schema数据库database。
提供对Druid,Mybatis-Plus,P6sy,Jndi的快速集成。
简化Druid和HikariCp配置,提供全局参数配置。
提供自定义数据源来源接口(默认使用yml或properties配置)。
提供项目启动后增减数据源方案。
提供Mybatis环境下的 纯读写分离 方案。
使用spel动态参数解析数据源,如从session,header或参数中获取数据源。(多租户架构神器)
提供多层数据源嵌套切换。(ServiceA >>> ServiceB >>> ServiceC,每个Service都是不同的数据源)
提供 不使用注解 而 使用 正则 或 spel 来切换数据源方案(实验性功能)。
基于seata的分布式事务支持。


==============================================================================================================

核心配置类
DynamicDataSourceAutoConfiguration

        @Bean
        @ConditionalOnMissingBean
        public DataSource dataSource(DynamicDataSourceProvider dynamicDataSourceProvider) {
            DynamicRoutingDataSource dataSource = new DynamicRoutingDataSource();  // 改造时自定义, 并覆盖核心方法
            dataSource.setPrimary(properties.getPrimary());
            dataSource.setStrategy(properties.getStrategy());
            dataSource.setProvider(dynamicDataSourceProvider);
            dataSource.setP6spy(properties.getP6spy());
            dataSource.setStrict(properties.getStrict());
            return dataSource;
        }


抽象动态获取数据源
AbstractRoutingDataSource

        /**
         * 子类实现决定最终数据源
         *
         * @return 数据源
         */
        protected abstract DataSource determineDataSource();

        @Override
        public Connection getConnection() throws SQLException {
            return determineDataSource().getConnection();
        }


核心动态数据源组件
DynamicRoutingDataSource

        /**
         * 所有数据库
         */
        private Map<String, DataSource> dataSourceMap = new LinkedHashMap<>();
        /**
         * 分组数据库
         */
        private Map<String, DynamicGroupDataSource> groupDataSources = new ConcurrentHashMap<>();

        @Override
        public DataSource determineDataSource() {
            return getDataSource(DynamicDataSourceContextHolder.peek());
        }

        private DataSource determinePrimaryDataSource() {
            log.debug("从默认数据源中返回数据");
            return groupDataSources.containsKey(primary) ? groupDataSources.get(primary).determineDataSource() : dataSourceMap.get(primary);
        }

        /**
         * 获取当前所有的数据源
         *
         * @return 当前所有数据源
         */
        public Map<String, DataSource> getCurrentDataSources() {
            return dataSourceMap;
        }

        /**
         * 获取的当前所有的分组数据源
         *
         * @return 当前所有的分组数据源
         */
        public Map<String, DynamicGroupDataSource> getCurrentGroupDataSources() {
            return groupDataSources;
        }

        /**
         * 获取数据源
         *
         * @param ds 数据源名称
         * @return 数据源
         */
        public DataSource getDataSource(String ds) {
            if (StringUtils.isEmpty(ds)) {
                return determinePrimaryDataSource();
            } else if (!groupDataSources.isEmpty() && groupDataSources.containsKey(ds)) {
                log.debug("从 {} 组数据源中返回数据源", ds);
                return groupDataSources.get(ds).determineDataSource();
            } else if (dataSourceMap.containsKey(ds)) {
                log.debug("从 {} 单数据源中返回数据源", ds);
                return dataSourceMap.get(ds);
            }
            if (strict) {
                throw new RuntimeException("不能找到名称为" + ds + "的数据源");
            }
            return determinePrimaryDataSource();
        }


===================================================================================================

如果有特殊业务, 例如多数据源事务控制(单个节点(分布式事务另当别论)), 可以参考以上核心代码加以改造, 简记....................以防忘记!!!!!!!!!

 

posted @ 2020-12-16 17:46  Bevis  阅读(1474)  评论(0编辑  收藏  举报