如何一文快速了解Mybatis连接池和事务

1、Mybatis 的连接池技术

  Mybatis 的连接池是在 Mybatis 的主配置文件: SqlMapConfig.xml 配置文件中,通过<dataSource type=”pooled” / >来对 Mybatis 中的连接池进行配置。

1.1、Mybatis 连接池的分类

在 Mybatis 中我们将它的数据源 dataSource 分为以下几类:在这里插入图片描述
可以看出 Mybatis 将它自己的数据源分为三类:

  • UNPOOLED 不使用连接池的数据源
  • POOLED 使用连接池的数据源
  • JNDI 使用 JNDI 实现的数据源

具体结构如下:
在这里插入图片描述
  相应地,MyBatis 内部分别定义了实现了 java.sql.DataSource 接口的 UnpooledDataSource 类和 PooledDataSource 类来表示 UNPOOLED、POOLED 类型的数据源。
在这里插入图片描述
  在这三种数据源中,我们一般采用的是 POOLED 数据源(很多时候我们所说的数据源就是为了更好的管理数据库连接,也就是我们所说的连接池技术)。

1.2、Mybatis 中数据源的配置

<!-- 我们的数据源配置就是在Mybatis主配置文件: SqlMapConfig.xml 文件中,具体配置如下:-->
<!-- 配置数据源(连接池)信息 -->
<dataSource type="POOLED">
	<property name="driver" value="${jdbc.driver}"/>
	<property name="url" value="${jdbc.url}"/>
	<property name="username" value="${jdbc.username}"/>
	<property name="password" value="${jdbc.password}"/>
</dataSource>
<!--
MyBatis 在初始化时,根据<dataSource>的 type 属性来创建相应类型的的数据源 DataSource,即:
type=”POOLED”:MyBatis 会创建 PooledDataSource 实例
type=”UNPOOLED” : MyBatis 会创建 UnpooledDataSource 实例
type=”JNDI”:MyBatis 会从 JNDI 服务上查找 DataSource 实例,然后返回使用
-->

1.3、Mybatis 中 DataSource 的存取

  MyBatis 是通过工厂模式来创建数据源 DataSource 对象的, MyBatis 定义了抽象的工厂接
口:org.apache.ibatis.datasource.DataSourceFactory,通过其 getDataSource()方法返回数据源
DataSource。
下面是 DataSourceFactory 源码,具体如下:

package org.apache.ibatis.datasource;
import java.util.Properties;
import javax.sql.DataSource;
/**
* @author cjh
*/
public interface DataSourceFactory {
	void setProperties(Properties props);
	DataSource getDataSource();
}

  MyBatis 创建了 DataSource 实例后,会将其放到 Configuration 对象内的 Environment 对象中, 供以后使用。
具体分析过程如下:
1.先进入 XMLConfigBuilder 类中,可以找到如下代码:
在这里插入图片描述
2.分析 configuration 对象的 environment 属性,结果如下:
在这里插入图片描述

1.4、Mybatis 中连接的获取过程分析

  当我们需要创建 SqlSession 对象并需要执行 SQL 语句时,这时候 MyBatis 才会去调用 dataSource 对象来创建java.sql.Connection对象。也就是说,java.sql.Connection对象的创建一直延迟到执行SQL语句的时候。

@Test
public void testSql() throws Exception {
	InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
	SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
	SqlSession sqlSession = factory.openSession();
	List<User> list = sqlSession.selectList("findUserById",41);
	System.out.println(list.size());
}

  只有当第 4 句sqlSession.selectList(“findUserById”),才会触发 MyBatis 在底层执行下面这个方
法来创建 java.sql.Connection 对象。
如何证明它的加载过程呢?
我们可以通过断点调试,在 PooledDataSource 中找到如下 popConnection()方法,如下所示:
在这里插入图片描述
分析源代码,得出 PooledDataSource 工作原理如下:在这里插入图片描述
下面是连接获取的源代码:在这里插入图片描述
  最后我们可以发现,真正连接打开的时间点,只是在我们执行SQL语句时,才会进行。其实这样做我们也可以进一步发现,数据库连接是我们最为宝贵的资源,只有在要用到的时候,才去获取并打开连接,当我们用完了就再立即将数据库连接归还到连接池中。

2、Mybatis 的事务控制

2.1、JDBC 中事务的回顾

  在 JDBC 中我们可以通过手动方式将事务的提交改为手动方式,通过 setAutoCommit()方法就可以调整。
通过 JDK 文档,我们找到该方法如下:
在这里插入图片描述
  那么我们的 Mybatis 框架因为是对 JDBC 的封装,所以 Mybatis 框架的事务控制方式,本身也是用 JDBC的setAutoCommit()方法来设置事务提交方式的。

2.2、Mybatis 中事务提交方式

在控制台观察Mybatis执行CUD三类操作的控制台输出:
在这里插入图片描述
  这是我们的 Connection 的整个变化过程,通过分析我们能够发现之前的 CUD 操作过程中,我们都要手动进行事务的提交,原因是 setAutoCommit()方法,在执行时它的值被设置为 false 了,所以我们在 CUD 操作中,必须通过 sqlSession.commit()方法来执行提交操作。

2.3、Mybatis 自动提交事务的设置

  通过上面的研究和分析,现在我们一起思考,为什么 CUD 过程中必须使用 sqlSession.commit()提交事务?主要原因就是在连接池中取出的连接,都会将调用connection.setAutoCommit(false)方法,这样我们就必须使用 sqlSession.commit()方法,相当于使用了 JDBC 中的 connection.commit()方法实现事务提交。
  明白这一点后,我们现在一起尝试不进行手动提交,一样实现 CUD 操作。

// 利用 SqlSessionFactory 工厂传入 true 参数来创建 SqlSession 对象,
SqlSession session = factory.openSession(true);

所对应的 DefaultSqlSessionFactory 类的源代码:
在这里插入图片描述
  此时事务就设置为自动提交了,同样可以实现CUD操作时记录的保存。虽然这也是一种方式,但就编程而言,设置为自动提交方式为 false 再根据情况决定是否进行提交,这种方式更常用。因为我们可以根据业务情况来决定提交何时提交何时回滚。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值