• 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();
            }
    
    
    ===================================================================================================

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

  • 相关阅读:
    TTVNC 2.0 发布了
    软件收费问题,目前没有限制, 全部免费
    为什么服务器端要确认才能连接通过
    关于transfer file功能的使用?
    同一台机器上测试会出现很多黑块
    TTVNC 设计理念
    TTVNC 2.2发布
    redis连接池 jedis2.9.0.jar+commonspool22.4.2.jar
    Calendar add 方法 和set方法
    jar包读取包内properties文件
  • 原文地址:https://www.cnblogs.com/bevis-byf/p/14145258.html
Copyright © 2020-2023  润新知