MyBatis数据源模块分析

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/newbie0107/article/details/102691318

MyBatis不仅能集成第三方的数据源组件,如dbcp、c3p0、druid等,它自身也提供了数据源的实现,我们在设置MyBatis的配置文件时,就可以设置对应的选项,如下
在这里插入图片描述


我们可以看下MyBatis有关数据源相关的包,我们主要看其 unpooled 和 pooled 两种方式,我们先看非连接池方式连接数据库,我们看从包中可以发现 DataSourceFactory 类,没错我们 MyBatis 使用到了工厂模式来创建我们连接数据库的对象。
在这里插入图片描述

我们第三方数据源组件底层都是使用的JDBC来连接数据库的,就是需要符合JDBC的规范,所以数据源组件都要实现了 javax.sql.DataSource 接口。


我们之前在配置数据库时,只是简单的配置了其必需的属性
在这里插入图片描述

但是其实我们可以配置很多很多的信息,如何一个类的信息太多,我们创建就会比较的麻烦,所以我们这里就使用了工厂模式来为我们创建
在这里插入图片描述

我们先看看不使用连接池的连接工厂
在这里插入图片描述

在这里插入图片描述

至于上述的缓存已注册的数据库驱动类,是用来干什么的呢?这里先获取到了JDBC里的 DriverManager,然后将其所有的驱动全部加载到 registeredDrivers 之中
在这里插入图片描述

这里我们可以看看我们之前自己写的使用JDBC连接数据的是如何写的,我们一般都会先注册数据库的驱动
在这里插入图片描述
在这里插入图片描述

在我们mysql的 Driver 类中,就会将其全部注册到jdbc的 DriverManager 之中。
在这里插入图片描述

所以我们直接用JDBC连接数据库时会这样写,那么我们的MyBatis会不是类似呢?我们会发现我们MyBatis在连接数据库时,不使用连接池的时候和我们使用JDBC的时候也是差不多的。
在这里插入图片描述



在我们看完 unpooled 后,现在我们先看看MyBatis使用连接池来连接数据库,我们会发现其继承了 UnpooledDataSourceFactory,因为都是通过JDBC来连接数据库嘛,只是数据源不同,这里使用了连接池来连接数据库了。
在这里插入图片描述

这里我们再看看包中其余的三个类
在这里插入图片描述

  • PooledConnection: 使用动态代理封装了真正的数据库连接对象;
  • PoolState: 用于管理 PooledConnection 对象状态的组件,通过两个 list 分别管理空闲状态的连接资源和活跃状态的连接资源
  • PooledDataSource: 一个简单,同步的、线程安全的数据库连接池

这里我们 PooledConnection 使用了动态代理,对我们真正的数据库连接对象 Connection 对象进行增强,增加其原来没有的能力。
在这里插入图片描述

它既然实现了 InvocationHandler 接口,使用了 Jdk 的动态代理,肯定是想增强某些功能,那么它增强了什么呢?
在这里插入图片描述

然后再来看看 PoolState
在这里插入图片描述

最后就是我们的 PoolDataSource 类
在这里插入图片描述

现在基本的我们的介绍完了,这我们来看卡连接池中是如何获取和归还连接的。


首先我们先看获取连接的流程,首先当想要连接时,我们需要保证其并发安全性,然后判断空闲连接是否存在连接,若存在就直接冲空闲连接中取出一个连接来
在这里插入图片描述

否则的话,我们再查看其最大活跃连接数是否未达到最大的值,如果没有达到的话,则进行创建一个新的连接
在这里插入图片描述

如果已经达到了最大的连接数,我们就查看其活跃连接数中的第一个连接,也就是连接时间最长的那一个连接,我们来看看其是否超过了最长连接时候,如果超过了最长连接时间,我们记录下一些信息,然后判断是否有事务未提交,有的话直接将其回滚。然后我们用这个超时连接中与数据库真正的连接对象来创建一个新的连接对象。
在这里插入图片描述

如果已经达到了最大的连接数,且所有的连接都未超过最长连接时间时,那么我们本次连接只能进行等待,我们调用 wait 方法,等待我们连接池释放了连接来唤醒。
在这里插入图片描述

当我们通过连接池拿到了连接时,我们还需判断该连接是否是合法的,如果是,我们将该连接原有的未提交的事务进行回滚,然后将本次连接添加到活跃连接池中去
在这里插入图片描述

如果拿到的是非法连接,则记录其信息,将其连接置空,这样进行下一次循环,再次尝试获取连接池中的连接,淡然不是无限的循环,当获取非法连接达到一定的次数,就是抛出异常。
在这里插入图片描述
在这里插入图片描述


上述我们看完了连接池获取连接的过程,下次我们紧接着查看其归还连接的流程。


同样一开始加锁保证我们线程的安全性,然后我们在活跃的连接池中移除这次连接
在这里插入图片描述


然后我们还判断该次连接是否有效,有效的话再来判断判断我们连接池中的空闲连接数是否未达到最大值。


有效且未达到最大值的话,然后首先还是一样,判断其中是否有未提交的事务,有则将其回滚。然后我们利用该次连接在创建一个新的连接,将其放入空闲连接之中,将原连接置为非法,最后通过那些等待获取连接的请求。
在这里插入图片描述

若是有效,但是连接池中空闲连接数已满的时候,直接将其真实的连接关闭,并且将该次连接设为非法即可。
在这里插入图片描述

若是一开始判断连接就是非法的话,那直接记录下就可以了
在这里插入图片描述



另外在获取连接和归还连接的时候,我们经常会判断连接是否有效,这里我们看看是如何判断的


我们先判断下连接中真实的连接对象是否为空,并且进行连接数据库测试一下。
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/newbie0107/article/details/102691318