Mybatis中的数据源与连接池

来源:互联网 发布:淘宝号怎么看注册时间 编辑:程序博客网 时间:2024/05/18 16:15

Mybatis中的数据源与连接池

在使用Mybatis框架时需要对核心配置文件进行设置,其中就包括了数据源和连接池。
本文只进行原理的描述,不包含实际代码。

一、为什么要使用连接池?

创建一个Conncection代价是巨大的,因为创建了一个连接,在底层就与数据库建立了通信连接,连接之后往往只进行简单的sql操作,浪费了巨大的资源。

二、数据库连接池的基本思想

为数据库建立一个“连接池”,预先创建一定数量的连接,当需要连接时,只需从中取出一个,使用完毕之后再放回。

三、数据源与连接池的描述

1.数据源的分类

(1)UNPOOLED 不使用连接池的数据源                --用实现了java.sql.DataSource的UnpooledDataSource类来表示(2)POOLED 使用连接池的数据源                --用实现了java.sql.DataSource的PooledDataSource类来表示(3)JNDI 使用JNDI实现的数据源                --通过JNDI上下文中取值注释:PooledDataSource和UnpooledDataSource都实现了java.sql.DataSource接口。可是当PooledDataSource需要创建java.sql.Connection对象时,是通过UnpooledDataSource来创建的,因为在PooledDataSource中持有一个UnpooledDataSource的引用,PooledDataSource只是提供一种缓存连接池机制。

2.数据源DataSource的创建过程

Mybatis数据源DataSource对象的创建发生在MyBatis初始化过程中。(1)Mybatis初始化时,解析xml,根据<datasource>中的type属性来创建相应类型的DataSource。注释:Mybatis创建DataSource根据工厂模式,三种工厂分别是    UnpooledDataSourceFactory 实现了DataSourceFactory接口    JndiDataSourceFactory   实现了DataSourceFactory接口    PooledDataSourceFactory  继承了UnpooledDataSourceFactory(2)创建DataSource实例之后,会将实例放入Configuration对象中的Environment对象中。

3.DataSource什么时候创建Connection对象

创建SqlSession对象执行SQL语句时才调用相应的DataSource来创建Connection对象。例如执行到sqlSession.selectList("SELECT * FROM STUDENTS");  才创建Connection对象。

4.不使用连接池的UnpooledDataSource

使用UnpooledDataSource的getConnection(),每调用一次就会产生一个新的Connection实例对象。

5.使用了连接池的PooledDataSource

PooledDataSource将Connection对象包裹成PooledConnection对象放入PoolState类型容器中。Mybatis将PoolConnection分为两种状态:空闲状态(idle)和活动状态(active),这两种状态被分别存储到PoolState容器内的idleConnections和activeConnections两个List集合中。idleConnections:idle状态的PooledConnection放入其中,表示当前没被使用的连接,需要连接时,优先从中取出。当用完一个Connection对象后,又会被包裹成PooledConnection放到此集合中。activeConections:active状态的PoolConnection放入其中,表示正在使用。当需要连接时,优先从idleConnections中取,如果没有,就看activeConnections集合是否已经满了,没满的话PooledDataSource会创建出一个PooledConnection添加到这个集合中,并返回。

6.获取java.sql.Connection对象的过程

先看是否有空闲(idle)状态下的PooledConnection对象,如果有,就直接返回一个可用的PooledConnection对象;否则进行第2步。

查看活动状态的PooledConnection池activeConnections是否已满;如果没有满,则创建一个新的PooledConnection对象,然后放到activeConnections池中,然后返回此PooledConnection对象;否则进行第3步;

看最先进入activeConnections池中的PooledConnection对象是否已经过期:如果已经过期,从activeConnections池中移除此对象,然后创建一个新的PooledConnection对象,添加到activeConnections中,然后将此对象返回;否则进行第4步。

线程等待,循环2步(代码见参考资料)

7.java.sql.Connection对象的回收

如何将用完之后的连接自动放回连接池,而不是手动将Connection放到Pool连接池?
所以应该实现Connection对象调用了close()方法,实际上却是将对象添加到连接池。
这是要使用代理模式,为真正的Connection对象创建一个代理对象,
代理对象所有的方法都是调用相应的真正Connection对象的方法实现。当代理对象执行close()方法时,
要特殊处理,不调用真正Connection对象的close()方法,而是将Connection对象添加到连接池中。
具体代码见参考资料。

8.JNDI类型的数据源DataSource

对于JNDI类型的数据源DataSource的获取就比较简单,MyBatis定义了一个JndiDataSourceFactory工厂
来创建通过JNDI形式生成的DataSource。具体代码见参考资料。

参考资料

原创粉丝点击