精尽 MyBatis 源码分析 —— 事务模块

作者简介:大家好,我是smart哥,前中兴通讯、美团架构师,现某互联网公司CTO

联系qq:184480602,加我进群,大家一起学习,一起进步,一起对抗互联网寒冬

学习必须往深处挖,挖的越深,基础越扎实!

阶段1、深入多线程

阶段2、深入多线程设计模式

阶段3、深入juc源码解析


阶段4、深入jdk其余源码解析


阶段5、深入jvm源码解析

码哥源码部分

码哥讲源码-原理源码篇【2024年最新大厂关于线程池使用的场景题】

码哥讲源码【炸雷啦!炸雷啦!黄光头他终于跑路啦!】

码哥讲源码-【jvm课程前置知识及c/c++调试环境搭建】

​​​​​​码哥讲源码-原理源码篇【揭秘join方法的唤醒本质上决定于jvm的底层析构函数】

码哥源码-原理源码篇【Doug Lea为什么要将成员变量赋值给局部变量后再操作?】

码哥讲源码【你水不是你的错,但是你胡说八道就是你不对了!】

码哥讲源码【谁再说Spring不支持多线程事务,你给我抽他!】

终结B站没人能讲清楚红黑树的历史,不服等你来踢馆!

打脸系列【020-3小时讲解MESI协议和volatile之间的关系,那些将x86下的验证结果当作最终结果的水货们请闭嘴】

1. 概述

MyBatis 对数据库中的事务进行了抽象,其自身提供了相应的事务接口和简单实现。

在很多场景中,MyBatis 会与 Spring 框架集成,并由 Spring 框架管理事务

2. Transaction

org.apache.ibatis.transaction.Transaction ,事务接口。代码如下:

    public interface Transaction {
    
      /**
       * Retrieve inner database connection.
       * @return DataBase connection
       * @throws SQLException
       *           the SQL exception
       */
      Connection getConnection() throws SQLException;
    
      /**
       * Commit inner database connection.
       * @throws SQLException
       *           the SQL exception
       */
      void commit() throws SQLException;
    
      /**
       * Rollback inner database connection.
       * @throws SQLException
       *           the SQL exception
       */
      void rollback() throws SQLException;
    
      /**
       * Close inner database connection.
       * @throws SQLException
       *           the SQL exception
       */
      void close() throws SQLException;
    
      /**
       * Get transaction timeout if set.
       *
       * @return the timeout
       * @throws SQLException
       *           the SQL exception
       */
      Integer getTimeout() throws SQLException;
    
    }
2.1 JdbcTransaction

org.apache.ibatis.transaction.jdbc.JdbcTransaction ,实现 Transaction 接口,基于 JDBC 的事务实现类。代码如下:

    // JdbcTransaction.java
    
    public class JdbcTransaction implements Transaction {
    
        private static final Log log = LogFactory.getLog(JdbcTransaction.class);
    
        /**
         * Connection 对象
         */
        protected Connection connection;
        /**
         * DataSource 对象
         */
        protected DataSource dataSource;
        /**
         * 事务隔离级别
         */
        protected TransactionIsolationLevel level;
        /**
         * 是否自动提交
         */
        protected boolean autoCommit;
    
        public JdbcTransaction(DataSource ds, TransactionIsolationLevel desiredLevel, boolean desiredAutoCommit) {
            dataSource = ds;
            level = desiredLevel;
            autoCommit = desiredAutoCommit;
        }
    
        public JdbcTransaction(Connection connection) {
            this.connection = connection;
        }
    
        @Override
        public Connection getConnection() throws SQLException {
            // 连接为空,进行创建
            if (connection == null) {
                openConnection();
            }
            return connection;
        }
    
        @Override
        public void commit() throws SQLException {
            // 非自动提交,则执行提交事务
            if (connection != null && !connection.getAutoCommit()) {
                if (log.isDebugEnabled()) {
                    log.debug("Committing JDBC Connection [" + connection + "]");
                }
                connection.commit();
            }
        }
    
        @Override
        public void rollback() throws SQLException {
            // 非自动提交。则回滚事务
            if (connection != null && !connection.getAutoCommit()) {
                if (log.isDebugEnabled()) {
                    log.debug("Rolling back JDBC Connection [" + connection + "]");
                }
                connection.rollback();
            }
        }
    
        @Override
        public void close() throws SQLException {
            if (connection != null) {
                // 重置连接为自动提交
                resetAutoCommit();
                if (log.isDebugEnabled()) {
                    log.debug("Closing JDBC Connection [" + connection + "]");
                }
                // 关闭连接
                connection.close();
            }
        }
    
        /**
         * 设置指定的 autoCommit 属性
         *
         * @param desiredAutoCommit 指定的 autoCommit 属性
         */
        protected void setDesiredAutoCommit(boolean desiredAutoCommit) {
            try {
                if (connection.getAutoCommit() != desiredAutoCommit) {
                    if (log.isDebugEnabled()) {
                        log.debug("Setting autocommit to " + desiredAutoCommit + " on JDBC Connection [" + connection + "]");
                    }
                    connection.setAutoCommit(desiredAutoCommit);
                }
            } catch (SQLException e) {
                // Only a very poorly implemented driver would fail here,
                // and there's not much we can do about that.
                throw new TransactionException("Error configuring AutoCommit.  "
                        + "Your driver may not support getAutoCommit() or setAutoCommit(). "
                        + "Requested setting: " + desiredAutoCommit + ".  Cause: " + e, e);
            }
        }
    
        /**
         * 重置 autoCommit 属性
         */
        protected void resetAutoCommit() {
            try {
                if (!connection.getAutoCommit()) {
                    // MyBatis does not call commit/rollback on a connection if just selects were performed.
                    // Some databases start transactions with select statements
                    // and they mandate a commit/rollback before closing the connection.
                    // A workaround is setting the autocommit to true before closing the connection.
                    // Sybase throws an exception here.
                    if (log.isDebugEnabled()) {
                        log.debug("Resetting autocommit to true on JDBC Connection [" + connection + "]");
                    }
                    connection.setAutoCommit(true);
                }
            } catch (SQLException e) {
                if (log.isDebugEnabled()) {
                    log.debug("Error resetting autocommit to true "
                            + "before closing the connection.  Cause: " + e);
                }
            }
        }
    
        /**
         * 获得 Connection 对象
         *
         * @throws SQLException 获得失败
         */
        protected void openConnection() throws SQLException {
            if (log.isDebugEnabled()) {
                log.debug("Opening JDBC Connection");
            }
            // 获得连接
            connection = dataSource.getConnection();
            // 设置隔离级别
            if (level != null) {
                connection.setTransactionIsolation(level.getLevel());
            }
            // 设置 autoCommit 属性
            setDesiredAutoCommit(autoCommit);
        }
    
        @Override
        public Integer getTimeout() throws SQLException {
            return null;
        }
    
    }
2.2 ManagedTransaction

org.apache.ibatis.transaction.managed.ManagedTransaction ,实现 Transaction 接口,基于容器管理的事务实现类。代码如下:

    public class ManagedTransaction implements Transaction {
    
        private static final Log log = LogFactory.getLog(ManagedTransaction.class);
    
        /**
         * Connection 对象
         */
        private Connection connection;
        /**
         * DataSource 对象
         */
        private DataSource dataSource;
        /**
         * 事务隔离级别
         */
        private TransactionIsolationLevel level;
        /**
         * 是否关闭连接
         *
         * 这个属性是和 {@link org.apache.ibatis.transaction.jdbc.JdbcTransaction} 不同的
         */
        private final boolean closeConnection;
    
        public ManagedTransaction(Connection connection, boolean closeConnection) {
            this.connection = connection;
            this.closeConnection = closeConnection;
        }
    
        public ManagedTransaction(DataSource ds, TransactionIsolationLevel level, boolean closeConnection) {
            this.dataSource = ds;
            this.level = level;
            this.closeConnection = closeConnection;
        }
    
        @Override
        public Connection getConnection() throws SQLException {
            // 连接为空,进行创建
            if (this.connection == null) {
                openConnection();
            }
            return this.connection;
        }
    
        @Override
        public void commit() throws SQLException {
            // Does nothing
        }
    
        @Override
        public void rollback() throws SQLException {
            // Does nothing
        }
    
        @Override
        public void close() throws SQLException {
            // 如果开启关闭连接功能,则关闭连接
            if (this.closeConnection && this.connection != null) {
                if (log.isDebugEnabled()) {
                    log.debug("Closing JDBC Connection [" + this.connection + "]");
                }
                this.connection.close();
            }
        }
    
        protected void openConnection() throws SQLException {
            if (log.isDebugEnabled()) {
                log.debug("Opening JDBC Connection");
            }
            // 获得连接
            this.connection = this.dataSource.getConnection();
            // 设置隔离级别
            if (this.level != null) {
                this.connection.setTransactionIsolation(this.level.getLevel());
            }
        }
    
        @Override
        public Integer getTimeout() throws SQLException {
            return null;
        }
    
    }

3. TransactionFactory

org.apache.ibatis.transaction.TransactionFactory ,Transaction 工厂接口。代码如下:

    public interface TransactionFactory {
    
        /**
         * Sets transaction factory custom properties.
         *
         * 设置工厂的属性
         *
         * @param props 属性
         */
        void setProperties(Properties props);
    
        /**
         * Creates a {@link Transaction} out of an existing connection.
         *
         * 创建 Transaction 事务
         *
         * @param conn Existing database connection
         * @return Transaction
         * @since 3.1.0
         */
        Transaction newTransaction(Connection conn);
    
        /**
         * Creates a {@link Transaction} out of a datasource.
         *
         * 创建 Transaction 事务
         *
         * @param dataSource DataSource to take the connection from
         * @param level      Desired isolation level
         * @param autoCommit Desired autocommit
         * @return Transaction
         * @since 3.1.0
         */
        Transaction newTransaction(DataSource dataSource, TransactionIsolationLevel level, boolean autoCommit);
    
    }
3.1 JdbcTransactionFactory

org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory ,实现 TransactionFactory 接口,JdbcTransaction 工厂实现类。代码如下:

    // JdbcTransactionFactory.java
    
    public class JdbcTransactionFactory implements TransactionFactory {
    
        @Override
        public void setProperties(Properties props) {
        }
    
        @Override
        public Transaction newTransaction(Connection conn) {
            // 创建 JdbcTransaction 对象
            return new JdbcTransaction(conn);
        }
    
        @Override
        public Transaction newTransaction(DataSource ds, TransactionIsolationLevel level, boolean autoCommit) {
            // 创建 JdbcTransaction 对象
            return new JdbcTransaction(ds, level, autoCommit);
        }
    
    }
3.2 ManagedTransactionFactory
    public class ManagedTransactionFactory implements TransactionFactory {
    
        /**
         * 是否关闭连接
         */
        private boolean closeConnection = true;
    
        @Override
        public void setProperties(Properties props) {
            // 获得是否关闭连接属性
            if (props != null) {
                String closeConnectionProperty = props.getProperty("closeConnection");
                if (closeConnectionProperty != null) {
                    closeConnection = Boolean.valueOf(closeConnectionProperty);
                }
            }
        }
    
        @Override
        public Transaction newTransaction(Connection conn) {
            // 创建 ManagedTransaction 对象
            return new ManagedTransaction(conn, closeConnection);
        }
    
        @Override
        public Transaction newTransaction(DataSource ds, TransactionIsolationLevel level, boolean autoCommit) {
            // Silently ignores autocommit and isolation level, as managed transactions are entirely
            // controlled by an external manager.  It's silently ignored so that
            // code remains portable between managed and unmanaged configurations.
            // 创建 ManagedTransaction 对象
            return new ManagedTransaction(ds, level, closeConnection);
        }
    
    }

  • 6
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值