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


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

如果有特殊業務, 例如多數據源事務控制(單個節點(分布式事務另當別論)), 可以參考以上核心代碼加以改造, 簡記....................以防忘記!!!!!!!!!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM