mybatis plus动态数据源切换及查询过程浅析

mybatis plus多数据源切换

mybatis plus多数据源切换使用注解 @DS
DS注解作为多数据源切点,具体实现作用主要由两个类完成
DynamicDataSourceAnnotationAdvisor
DynamicDataSourceAnnotationInterceptor

DS多数据源切换实现

1.DynamicDataSourceAnnotationAdvisor类实现切面配置,其中AnnotationMatchingPointcut用于寻找切点,进入可看到支持类和方法的切点,多个切点会执行多次,根据代码顺序,方法的切点执行晚于类切点,所以方法的切点会覆盖类,但是都会被执行

2.DynamicDataSourceAnnotationInterceptor 实现切面功能,匹配到切点后,根据切点值(数据源id)设置当前线程有效数据源私有变量,用于执行查询时动态数据源能获取,执行完毕会清楚此变量,此存储功能由DynamicDataSourceContextHolder提供

3.执行时动态数据源确定,mybatisplus动态数据源实现类为DynamicRoutingDataSource,其维护一个map保存所有配置的数据源,以数据源ID作为key,执行查询时,获取连接,交由spring事务管理器SpringManagedTransaction进行连接获取,若当前存在连接则直接返回,不存在是创建连接,只有创建连接时,才有机会切换数据源,此处需要注意的是,同一事务下,使用的同一个sqlSession,执行查询时使用的是同一个执行器executor,最终使用的是同一个事务管理器,所以获取连接时无法创建新连接,mybatisplus切换数据源功能失效,代码无法被执行

此处逻辑较多,一笔带过有点草率,后续附带mybatisplus查询过程,感兴趣的老铁一会在看。

4.动态数据源敲定,接第3步,若当前事务管理器还未创建连接,那就打开一个连接,使用DataSourceUtils获取一个连接,入参为mybatisplus的动态数据源DynamicRoutingDataSource,一步步往下巴拉,忽略不需要代码,最终执行到了这一句:
Connection con = dataSource.getConnection();
使用DynamicRoutingDataSource获取连接,瞧,兜兜转转,最终怎么找连接,敲定数据源又交给了mybatisplus,getConnection方法在其父级AbstractRoutingDataSource中,使用this.determineDataSource().getConnection()获取连接,.getConnection()是数据源获取连接方法,那确定数据源顾名思义就是determineDataSource方法了,这个方法的实现就在DynamicRoutingDataSource中,来瞧瞧!是不是瞬间舒服了,根据第二部切面设置的数据源,这个返回对应的数据源。

5.主要逻辑已经清楚了,那么来延伸下,如何手动切换数据源mybatisplus切换数据源主要是使用DynamicDataSourceContextHolder的线程独享变量,那么如果没有DS切点,无法自动切换数据源,需要切换数据源时就可以使用DynamicDataSourceContextHolder.setDataSourceLookupKey 设置数据源,使用完后再清除掉(默认数据源生效),这个方法同第4步所提的事务问题,存在事务则无法切换(压根就不执行 只设置无法执行切换代码),如果将要执行的代码已存在切点,则执行前手动设置也是无效的,因为切点会覆盖你的设置。

注:如果需要在事务存在的情况下切换数据源,则估计要覆盖掉或替换掉spring的事务管理器,此处待后续再议。如果事务内仍需要切换数据源,则需要单独定义service并设置切点,设置此切点的事务传播行为为PROPAGATION__REQUIRES_NEW,则执行切面方法时单独创建一个事务,数据源会自动切换。

mybatisplus执行查询过程

现分析mybatisplus执行查询过程

1.执行selectById方法,执行return this.baseMapper.selectById(id);经过springaop切面进行一系列巴拉巴拉的处理,最终进入mybatisplus PageMapperMethod类中执行execute方法,根据sql类型进行不同处理,分新增,修改,删除,查询,我们本次只关注查询,查询里也有很多东西。

可以看到此处提供多种返回值的查询,有空返回值,多个,map,游标,及啥也不是。空值查询猜测是另有处理器直接处理返回值,此处不做延伸了,有需要再议,回到按照ID查询及进入啥也不是分支,本次查询不是分页查询,直接进入selectOne ,result = sqlSession.selectOne(this.command.getName(), param); 这里的sqlSession是SqlSessionTemplate,执行selectOne时首先获取sqlSession(默认为DefaultSelSession)

2.获取真正的sqlSession并执行selectOne查询,首先使用事务管理器获取缓存的sqlSession的持有者(sqlSession包装类),不存在则创建并缓存注册。

得到真正的sqlSession后,执行selectOne,发现还是执行的selectList,然后就是大众写法,size=1返回get(0),否则为空或者报错结果集太多。

3.来看看selectList在干嘛,先获取查询语句相关的MappedStatement,然后使用执行器executor执行查询 this.executor.query
执行器是啥?怎么来的?

执行器是sqlSession内部的一个属性,sqlSession其实也是个外包装,提供了一堆规范化的操作,但是并不直接实现这些操作,而是交给执行器,执行器来执行增删改查,默认使用的是SimpleExecutor,就以他入手,SimpleExecutor继承抽象类BaseExecutor,BaseExecutor实现了Executor接口,这个query就在BaseExecutor中:这里主要是获取执行的sql,以及根据执行语句和入参来生成一个缓存的key,会缓存查询结果,如果下次再来个一毛一样的查询 就直接用缓存了,不查了,这个就是mybatis的一级缓存,缓存使用的是一个封装的类PerpetualCache,最终对应的就是一个map :
private Map<Object, Object> cache = new HashMap();

4.执行数据库查询queryFromDatabase -> doQuery,这里和spring一个习惯,真正做事情的都是doXXX前面都是铺垫前戏,看的人云里雾里的
这个doQuery的实现在SimpleExecutor中,进入查看,
先创建了一个Statement,这个我知道,是jdbc里的东西,jdbc大概就是加载驱动,获取连接,打开一个执行语句块,然后执行获取结果。具体这个东西学名和作用还是百度下吧:
Statement 对象用于把 SQL 语句发送到 DBMS。你只须简单地创建一个 Statement 对象并且然后执行它,使用适当的方法执行你发送的 SQL 语句。
这个也就是jdbc层面的sqlSession了吧。

创建完Statement后就会执行查询,先看来看Statement如何创建

5.Statement创建,创建第一步获取connection,这个就涉及到数据源了吧,进入查看,使用事务管理器Transaction获取连接,默认的事务管理器是SpringManagedTransaction,然后获取数据源,最终创建或使用一个已有的连接并返回,进而创建出一个Statement,其他细节已无心再细究,不影响本次分析目的。

6.执行查询,直接略过看最终执行处,doFinish-> query ,执行jdbc的PreparedStatement.execute,之后的代码就先不看了,看意思就是将原始ResultSet结果集转化为list。

到此这篇关于mybatis plus动态数据源切换及查询过程浅析的文章就介绍到这了,更多相关mybatis plus动态数据源切换内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • SpringBoot整合MyBatisPlus配置动态数据源的方法

    MybatisPlus特性 •无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑 •损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作 •强大的 CRUD 操作:内置通用 Mapper.通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求 •支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错 •支持多种数据库:支持 MySQL.MariaDB.Ora

  • mybatis plus动态数据源切换及查询过程浅析

    mybatis plus多数据源切换 mybatis plus多数据源切换使用注解 @DS DS注解作为多数据源切点,具体实现作用主要由两个类完成 DynamicDataSourceAnnotationAdvisor DynamicDataSourceAnnotationInterceptor DS多数据源切换实现 1.DynamicDataSourceAnnotationAdvisor类实现切面配置,其中AnnotationMatchingPointcut用于寻找切点,进入可看到支持类和方法的

  • 详解SpringBoot+Mybatis实现动态数据源切换

    业务背景 电商订单项目分正向和逆向两个部分:其中正向数据库记录了订单的基本信息,包括订单基本信息.订单商品信息.优惠卷信息.发票信息.账期信息.结算信息.订单备注信息.收货人信息等:逆向数据库主要包含了商品的退货信息和维修信息.数据量超过500万行就要考虑分库分表和读写分离,那么我们在正向操作和逆向操作的时候,就需要动态的切换到相应的数据库,进行相关的操作. 解决思路 现在项目的结构设计基本上是基于MVC的,那么数据库的操作集中在dao层完成,主要业务逻辑在service层处理,controll

  • SpringBoot Mybatis动态数据源切换方案实现过程

    背景 最近让我做一个大数据的系统,分析了一下,麻烦的地方就是多数据源切换抽取数据.考虑到可以跨服务器跨数据库抽数,再整理数据,就配置了这个动态数据源的解决方案.在此分享给大家. 实现方案 数据库配置文件 我们项目使用的是yml形式的配置文件,采用的是hikari的数据库连接池.第一步我们自然是配置多个数据库源头. 我们找到spring的datasource,在下方配置三个数据源. spring: application: name: dynamicDatasource datasource: t

  • Spring Boot + Mybatis 实现动态数据源案例分析

    动态数据源 在很多具体应用场景的时候,我们需要用到动态数据源的情况,比如多租户的场景,系统登录时需要根据用户信息切换到用户对应的数据库.又比如业务A要访问A数据库,业务B要访问B数据库等,都可以使用动态数据源方案进行解决.接下来,我们就来讲解如何实现动态数据源,以及在过程中剖析动态数据源背后的实现原理. 实现案例 本教程案例基于 Spring Boot + Mybatis + MySQL 实现. 数据库设计 首先需要安装好MySQL数据库,新建数据库 master,slave,分别创建用户表,用

  • 详解Spring Boot + Mybatis 实现动态数据源

    动态数据源 在很多具体应用场景的时候,我们需要用到动态数据源的情况,比如多租户的场景,系统登录时需要根据用户信息切换到用户对应的数据库.又比如业务A要访问A数据库,业务B要访问B数据库等,都可以使用动态数据源方案进行解决.接下来,我们就来讲解如何实现动态数据源,以及在过程中剖析动态数据源背后的实现原理. 实现案例 本教程案例基于 Spring Boot + Mybatis + MySQL 实现. 数据库设计 首先需要安装好MySQL数据库,新建数据库 example,创建example表,用来测

  • mybatis的动态SQL和模糊查询实例详解

    现在以一个例子来介绍mybatis的动态SQL和模糊查询:通过多条件查询用户记录,条件为姓名模糊匹配,并且年龄在某两个值之间. 新建表d_user: create table d_user( id int primary key auto_increment, name varchar(10), age int(3) ); insert into d_user(name,age) values('Tom',12); insert into d_user(name,age) values('Bob

  • Java注解实现动态数据源切换的实例代码

    当一个项目中有多个数据源(也可以是主从库)的时候,我们可以利用注解在mapper接口上标注数据源,从而来实现多个数据源在运行时的动态切换. 实现原理 在Spring 2.0.1中引入了AbstractRoutingDataSource, 该类充当了DataSource的路由中介, 能有在运行时, 根据某种key值来动态切换到真正的DataSource上. 看下AbstractRoutingDataSource: 复制代码 代码如下: public abstract class AbstractR

  • Spring(AbstractRoutingDataSource)实现动态数据源切换示例

    一.前言 近期一项目A需实现数据同步到另一项目B数据库中,在不改变B项目的情况下,只好选择项目A中切换数据源,直接把数据写入项目B的数据库中.这种需求,在数据同步与定时任务中经常需要. 那么问题来了,该如何解决多数据源问题呢?不光是要配置多个数据源,还得能灵活动态的切换数据源.以spring+hibernate框架项目为例: 单个数据源绑定给sessionFactory,再在Dao层操作,若多个数据源的话,那不是就成了下图: 可见,sessionFactory都写死在了Dao层,若我再添加个数据

  • 通过springboot+mybatis+druid配置动态数据源

    一.建数据库和表 1.数据库demo1放一张user表 SET FOREIGN_KEY_CHECKS=0; -- ---------------------------- -- Table structure for user -- ---------------------------- DROP TABLE IF EXISTS `user`; CREATE TABLE `user` ( `id` int(11) NOT NULL, `name` varchar(255) DEFAULT NU

  • 通过Spring Boot配置动态数据源访问多个数据库的实现代码

    之前写过一篇博客<Spring+Mybatis+Mysql搭建分布式数据库访问框架>描述如何通过Spring+Mybatis配置动态数据源访问多个数据库.但是之前的方案有一些限制(原博客中也描述了):只适用于数据库数量不多且固定的情况.针对数据库动态增加的情况无能为力. 下面讲的方案能支持数据库动态增删,数量不限. 数据库环境准备 下面一Mysql为例,先在本地建3个数据库用于测试.需要说明的是本方案不限数据库数量,支持不同的数据库部署在不同的服务器上.如图所示db_project_001.d

随机推荐