您的位置:首页 > 其它

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

2020-04-21 20:22 323 查看

文章目录

  • 2、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 再根据情况决定是否进行提交,这种方式更常用。因为我们可以根据业务情况来决定提交何时提交何时回滚。

    • 点赞
    • 收藏
    • 分享
    • 文章举报
    cjh-gdAcm997 发布了37 篇原创文章 · 获赞 5 · 访问量 3871 私信 关注
    内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
    标签: