上一篇 了解MyBatis框架实现CRUD操作及MyBatis配置文件参数:https://blog.csdn.net/weixin_44187963/article/details/104975306
目录
前面在学习JDBC的时候也已经提到过几种连接池,比如常见的c3p0、Druid的使用,在此基础上今天来看看MyBatis中关于连接池的使用~
连接池概述
连接池就是用于存储连接的容器,而之所以在实际开发中都会用到连接池呢,是因为连接池大大减少了我们在不断获取链连接释放连接过程中所消耗的时间。
而作为容器:
- 通常是一个线程安全的集合对象
- 而且集合必须实现队列的特性:先进先出
MyBatis连接池提供三种方式的配置
配置的位置就在主配置文件SqlMapConfig.xml中的datasource标签,其中的type属性就是采用何种连接池。
<dataSource type="POOLED">
-
POOLED:采用传统的javax.sql.datasource规范中的连接池,mybatis中有针对规范的实现
-
UNPOOLED:采用传统的获取连接的方式,虽然也实现了javax.sql.datasource接口,但是没有使用池的思想
-
JDNI:采用服务器提供的JNDI技术实现,来获取Datasource对象。如果不是web或maven的war工程是不能使用的
注:tomcat服务器采用的是dbcp连接池
MyBatis数据源DataSource分类
MyBatis内部定义了实现了java.sql.DataSource接口的UnpooledDataSource类来表示UNPOOLED、java.sql.DataSource接口的PooledDataSource类来表示POOLED类型的数据源。
使用了连接池的PooledDataSource
使用PooledDataSource的getConnection()方法来返回Connection对象的基本原理:
PooledDataSource将java.sql.Connection对象包裹成PooledConnection对象放到了PoolState类型的容器中维护。 MyBatis将连接池中的PooledConnection分为两种状态: 空闲状态(idle)和活动状态(active),这两种状态的PooledConnection对象分别被存储到PoolState容器内的idleConnections和activeConnections两个List集合中:
idleConnections:空闲状态PooledConnection对象被放置到此集合中,表示当前闲置的没有被使用的PooledConnection集合,调用PooledDataSource的getConnection()方法时,会优先从此集合中取PooledConnection对象。当用完一个java.sql.Connection对象时,MyBatis会将其包裹成PooledConnection对象放到此集合中。
activeConnections:活动状态的PooledConnection对象被放置到名为activeConnections的ArrayList中,表示当前正在被使用的PooledConnection集合,调用PooledDataSource的getConnection()方法时,会优先从idleConnections集合中取PooledConnection对象,如果没有,则看此集合是否已满,如果未满,PooledDataSource会创建出一个PooledConnection,添加到此集合中,并返回。
PooledDataSource 的getConnection()方法获取Connection对象的处理流程图:
不使用连接池的UnpooledDataSource
当 <dataSource>的type属性被配置成了”UNPOOLED”
<dataSource type="UNPOOLED">
MyBatis首先会实例化一个UnpooledDataSourceFactory工厂实例,然后通过.getDataSource()方法返回一个UnpooledDataSource实例对象引用。使用UnpooledDataSource的getConnection(),每调用一次就会产生一个新的Connection实例对象。
UnpooledDataSource会做以下事情:
1. 初始化驱动:判断driver驱动是否已经加载到内存中,如果还没有加载,则会动态地加载driver类,并实例化一个Driver对象,使用DriverManager.registerDriver()方法将其注册到内存中,以供后续使用。
2. 创建Connection对象:使用DriverManager.getConnection()方法创建连接。
3. 配置Connection对象:设置是否自动提交autoCommit和隔离级别isolationLevel。
4. 返回Connection对象。
MyBatis的事务管理机制
MyBatis的事务管理分为两种形式
-
使用JDBC的事务管理机制:即利用java.sql.Connection对象完成对事务的提交(commit())、回滚(rollback())、关闭(close())等
-
使用MANAGED的事务管理机制:这种机制MyBatis自身不会去实现事务管理,而是让程序的容器如(JBOSS,Weblogic)来实现对事务的管理
两者的类图如下:
1. 事务的配置
我们在使用MyBatis时,一般会在MyBatisXML配置文件中定义类似如下的信息:
<!--环境配置-->
<environments default="mysql">
<environment id="mysql">
<transactionManager type="jdbc"></transactionManager>
<!--数据库连接池-->
<dataSource type="UNPOOLED">
<!--数据库连接配置-->
<property name="driver" value="${driver}"></property>
<property name="url" value="${url}"></property>
<property name="username" value="${user}"></property>
<property name="password" value="${password}"></property>
</dataSource>
</environment>
</environments>
其中transactionManager type属性表示使用JDBC事务管理机制:
<transactionManager type="jdbc"></transactionManager>
2. 事务工厂的创建
MyBatis事务的创建是交给TransactionFactory 事务工厂来创建的,如果我们将<transactionManager>的type 配置为"JDBC",那么,在MyBatis初始化解析<environment>节点时,会根据type="JDBC"创建一个JdbcTransactionFactory工厂。
如果type = "JDBC", 则MyBatis会创建一个JdbcTransactionFactory.class 实例;如果type="MANAGED",则MyBatis会创建一个MangedTransactionFactory.class实例。
3. 事务的提交
在之前博客中有写到关于事务的提交我们都是通过手动提交:
@After//在测试方法执行之后进行
public void destroy() throws IOException {
//提交事务
session.commit();
session.close();
in.close();
}
那么如何实现事务的自动提交呢,看源码中有这样写:
所以在使用中factory.openSession(true)传参为true就表示事务的自动提交:
public void init() throws IOException {
in = Resources.getResourceAsStream("SqlMapConfig.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
session = factory.openSession(true);
userDao = session.getMapper(UserDao.class);
}