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

摘要:
com.baomidou<动态数据源弹簧启动机<版本>${dynamic.version}<dataSource.setPspy(properties.getP6spy());dataSource.setSstrict(properties.getStrict());
<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();
        }


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

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

免责声明:文章转载自《Spring-boot 数据源 事务 多数据源 以及 多数据源事务 问题 简单笔记》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Cookie原理centos6安装rabbitmq下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Mac系统安装Aircrack-ng破解附近wifi密码(1)

  第一步, 安装macport, 安装Xcode   安装macport macport 是一个工具 管理软件包的一个工具, 我们也可以通过别的方式安装Aircrack-ng, 但是通过macport安装Aircrack-ng的速度是最快的, (Mac系统要求安装Xcode, 可以参考macport的首页)   macport没安装的话通过:https:...

C语言集锦(三)Direct3D和GDI+的例子

0.前言   有些时候你可能想了解,如何用纯C语言来写Direct3D和GDI+的Demo。注意,下面的Direct3D例子不适用于TCC编译器,GDI+的例子是可以的。 1.Direct3D C语言的例子   几乎所有的D3D例子都是用COM和C++写的。C语言可以用D3D吗,StackOverflow上给出了答案:directx-programming...

filter 以及 orderBy的使用

filter用于关键字过滤操作,orderBy用于排序操作,运行界面如下: 点击标题Name与Email实现排序功能,输入框中输入关键字进行过滤,同时实现根据关键字进行过滤后进行排序操作: ng-repeat="user in users | filter:keyword | orderBy:sortField:reverse" index.html &...

redis 模糊搜索

参考:https://blog.csdn.net/dc_726/article/details/42784317 创建一条测试 数据 查询 (默认是 DB 0 ) 创建: set name xiaoming 查询: get name 1、模糊搜索查询 (redis 默认有16个DB , 0-15 ) Redis 模糊搜索 1、keys *   匹配数据库...

List.Select按字符串选择属性

不知道大家有没有遇到这样的情况:List使用Lambda表达式的时候,想要选择项的某个属性列。 例如,选择编号ID: 1 var idList=list.Select(o=>o.ID).ToList(); 又,想要选择名称: 1 var nameList=list.Select(o=>o.Name).ToList(); 可否将其抽象呢?下面是我...

php 结合redis 限制用户每日砍价次数

最近做的砍价活动的项目马上上线了 ,之前提出的是不限制用户的砍价次数,但是后面又说要改成限制次数。。。。。 需求就是每个商品的砍价数次做限制,后台可以限制用户每天的砍价次数。意思就是属于该活动的订单,每个好友过来帮你砍价,需要限制每日最大的次数(之前没有限制)。所以想到用redis ,redis 里面有键值可以设置过期时间,感觉很好用,直接上代码了: 首...