Mybatis-事务对象源码解析

Mybatis3.5.1源码分析

  1. Mybatis-SqlSessionFactoryBuilder,XMLConfigBuilder,XPathParser源码解析
  2. Mybatis-Configuration源码解析
  3. Mybatis-事务对象源码解析
  4. Mybatis-数据源源码解析
  5. Mybatis缓存策略源码解析
  6. Mybatis-DatabaseIdProvider源码解析
  7. Mybatis-TypeHandler源码解析
  8. Mybatis-Reflector源码解析
  9. Mybatis-ObjectFactory,ObjectWrapperFactory源码分析
  10. Mybatis-Mapper各类标签封装类源码解析
  11. Mybatis-XMLMapperBuilder,XMLStatmentBuilder源码分析
  12. Mybatis-MapperAnnotationBuilder源码分析
  13. [Mybatis-MetaObject,MetaClass源码解析]https://www.jianshu.com/p/f51fa552f30a)
  14. Mybatis-LanguageDriver源码解析
  15. Mybatis-SqlSource源码解析
  16. Mybatis-SqlNode源码解析
  17. Mybatis-KeyGenerator源码解析
  18. Mybatis-Executor源码解析
  19. Mybatis-ParameterHandler源码解析
  20. Mybatis-StatementHandler源码解析
  21. Mybatis-DefaultResultSetHandler(一)源码解析
  22. Mybatis-DefaultResultSetHandler(二)源码解析
  23. Mybatis-ResultHandler,Cursor,RowBounds 源码分析
  24. Mybatis-MapperProxy源码解析
  25. Mybatis-SqlSession源码解析
  26. Mybatis-Interceptor源码解析

TransactionIsolationLevel

/**
 *    Copyright 2009-2018 the original author or authors.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */
package org.apache.ibatis.session;

import java.sql.Connection;

/**
 * 事务隔离等级
 * 

* 参考博客:https://blog.csdn.net/jiangwei0910410003/article/details/24960785 *

* @author Clinton Begin */ public enum TransactionIsolationLevel { NONE(Connection.TRANSACTION_NONE), /** *(读取未提交内容)级别 */ READ_COMMITTED(Connection.TRANSACTION_READ_COMMITTED), /** * 读取提交内容 */ READ_UNCOMMITTED(Connection.TRANSACTION_READ_UNCOMMITTED), /** * 可重读 */ REPEATABLE_READ(Connection.TRANSACTION_REPEATABLE_READ), /** * 串行化 */ SERIALIZABLE(Connection.TRANSACTION_SERIALIZABLE); private final int level; TransactionIsolationLevel(int level) { this.level = level; } public int getLevel() { return level; } }

TransactionFactory

/**
 *    Copyright 2009-2019 the original author or authors.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */
package org.apache.ibatis.transaction;

import java.sql.Connection;
import java.util.Properties;

import javax.sql.DataSource;

import org.apache.ibatis.session.TransactionIsolationLevel;

/**
 * Creates {@link Transaction} instances.
 * 事务工厂
 * @author Clinton Begin
 */
public interface TransactionFactory {

  /**
   * 设置属性
   * Sets transaction factory custom properties.
   * @param props 属性集
   */
  void setProperties(Properties props);

  /**
   * 新建一个事务
   * Creates a {@link Transaction} out of an existing connection.
   * @param conn Existing database connection
   * @return Transaction 事务对象
   * @since 3.1.0
   */
  Transaction newTransaction(Connection conn);

  /**
   * 新建一个事务
   * Creates a {@link Transaction} out of a datasource.
   * @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);

}

JdbcTransactionFactory

/**
 *    Copyright 2009-2016 the original author or authors.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */
package org.apache.ibatis.transaction.jdbc;

import java.sql.Connection;
import java.util.Properties;

import javax.sql.DataSource;

import org.apache.ibatis.session.TransactionIsolationLevel;
import org.apache.ibatis.transaction.Transaction;
import org.apache.ibatis.transaction.TransactionFactory;

/**
 * Creates {@link JdbcTransaction} instances.
 * JDBC事务工厂
 * @author Clinton Begin
 *
 * @see JdbcTransaction
 */
public class JdbcTransactionFactory implements TransactionFactory {

  /**
   * 设置属性
   * @param props 属性集
   */
  @Override
  public void setProperties(Properties props) {
  }

  /**
   * 新建Jdbc事务对象
   * @param conn Existing database connection 数据库连接
   * @return Jdbc事务对象
   */
  @Override
  public Transaction newTransaction(Connection conn) {
    //新建Jdbc事务对象
    return new JdbcTransaction(conn);
  }

  /**
   * 新建Jdbc事务对象
   * @param ds 数据源
   * @param level Desired isolation level  事务隔离等级
   * @param autoCommit Desired autocommit 是否自动提交
   * @return Jdbc事务对象
   */
  @Override
  public Transaction newTransaction(DataSource ds, TransactionIsolationLevel level, boolean autoCommit) {
    //新建Jdbc事务对象
    return new JdbcTransaction(ds, level, autoCommit);
  }
}

ManagedTransactionFactory

/**
 *    Copyright 2009-2016 the original author or authors.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */
package org.apache.ibatis.transaction.managed;

import java.sql.Connection;
import java.util.Properties;

import javax.sql.DataSource;

import org.apache.ibatis.session.TransactionIsolationLevel;
import org.apache.ibatis.transaction.Transaction;
import org.apache.ibatis.transaction.TransactionFactory;

/**
 * Creates {@link ManagedTransaction} instances.
 * {@link ManagedTransaction} 工厂。
 * @author Clinton Begin
 *
 * @see ManagedTransaction
 */
public class ManagedTransactionFactory implements TransactionFactory {

  private boolean closeConnection = true;

  /**
   * 接收一个关闭连接closeConnection的属性。ManagedTransaction它默认会关闭连接,然而一些容器并不希望这样,
   * 因此需要将 closeConnection 属性设置为 false 来阻止它默认的关闭行为。
   * @param props
   */
  @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) {
    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.
    //默默地忽略autocommit和隔离级别,管理事务完全由外部控制经理。它默默地忽略代码之间仍然是便携式托管和非托管的配置。
    // ManagedTransaction:MyBatis自身不会去实现事务管理,而是让程序的容器如(JBOSS,Weblogic)来实现对事务的管理
    return new ManagedTransaction(ds, level, closeConnection);
  }
}

Transaction

/**
 *    Copyright 2009-2019 the original author or authors.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */
package org.apache.ibatis.transaction;

import java.sql.Connection;
import java.sql.SQLException;

/**
 * Wraps a database connection.
 * Handles the connection lifecycle that comprises: its creation, preparation, commit/rollback and close.
 * 包装一个数据库连接。
 * 处理连接的生命周期包括:创建、准备、提交/回滚并关闭。;
 * @author Clinton Begin
 */
public interface Transaction {

  /**
   * 获取数据库连接
   * Retrieve inner database connection.
   * @return DataBase connection
   * @throws SQLException
   */
  Connection getConnection() throws SQLException;

  /**
   * 提交数据库连接
   * Commit inner database connection.
   * @throws SQLException
   */
  void commit() throws SQLException;

  /**
   * 回退数据库连接
   * Rollback inner database connection.
   * @throws SQLException
   */
  void rollback() throws SQLException;

  /**
   * 关闭数据库连接
   * Close inner database connection.
   * @throws SQLException
   */
  void close() throws SQLException;

  /**
   * 获取事务超时时长
   * Get transaction timeout if set.
   * @throws SQLException
   */
  Integer getTimeout() throws SQLException;

}

JdbcTransaction

/**
 *    Copyright 2009-2019 the original author or authors.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */
package org.apache.ibatis.transaction.jdbc;

import java.sql.Connection;
import java.sql.SQLException;
import javax.sql.DataSource;

import org.apache.ibatis.logging.Log;
import org.apache.ibatis.logging.LogFactory;
import org.apache.ibatis.session.TransactionIsolationLevel;
import org.apache.ibatis.transaction.Transaction;
import org.apache.ibatis.transaction.TransactionException;

/**
 * {@link Transaction} that makes use of the JDBC commit and rollback facilities directly.
 * It relies on the connection retrieved from the dataSource to manage the scope of the transaction.
 * Delays connection retrieval until getConnection() is called.
 * Ignores commit or rollback requests when autocommit is on.
 * JDBC事务封装
 * @author Clinton Begin
 *
 * @see JdbcTransactionFactory
 */
public class JdbcTransaction implements Transaction {

  /**
   * 日志对象
   */
  private static final Log log = LogFactory.getLog(JdbcTransaction.class);

  /**
   * 数据连接
   */
  protected Connection connection;
  /**
   * 数据源
   */
  protected DataSource dataSource;
  /**
   * 事务隔离等级
   */
  protected TransactionIsolationLevel level;
  /**
   * 是否自动提交
   */
  protected boolean autoCommit;

  /**
   *
   * @param ds 数据库数据源
   * @param desiredLevel 事务隔离级别,设置null时,隔离级别由数据库自行配置
   * @param desiredAutoCommit 是否自动提交事务
   */
  public JdbcTransaction(DataSource ds, TransactionIsolationLevel desiredLevel, boolean desiredAutoCommit) {
    dataSource = ds;
    level = desiredLevel;
    autoCommit = desiredAutoCommit;
  }

  /**
   *
   * @param connection 数据库连接
   */
  public JdbcTransaction(Connection connection) {
    this.connection = connection;
  }

  @Override
  public Connection getConnection() throws SQLException {
    if (connection == null) {
      openConnection();
    }
    return connection;
  }

  /**
   * 提交事务,在没有设置自动提交事务,才会提交事务。
   * @throws SQLException
   */
  @Override
  public void commit() throws SQLException {
    if (connection != null && !connection.getAutoCommit()) {
      if (log.isDebugEnabled()) {
        log.debug("Committing JDBC Connection [" + connection + "]");
      }
      connection.commit();
    }
  }

  /**
   * 回退事务,在没有设置自动提交事务,才会回退事务。
   * @throws SQLException
   */
  @Override
  public void rollback() throws SQLException {
    if (connection != null && !connection.getAutoCommit()) {
      if (log.isDebugEnabled()) {
        log.debug("Rolling back JDBC Connection [" + connection + "]");
      }
      connection.rollback();
    }
  }

  /**
   * 关闭连接,关闭连接之前,会设置自动提交为true,以解决有些数据库读取事务时就开始事务了和授权了提交、回滚在关闭这个连接之前的问题
   * @throws SQLException
   */
  @Override
  public void close() throws SQLException {
    if (connection != null) {
      resetAutoCommit();
      if (log.isDebugEnabled()) {
        log.debug("Closing JDBC Connection [" + connection + "]");
      }
      connection.close();
    }
  }

  /**
   * 设置自动提交,
   * @param desiredAutoCommit 是否自动提交
   */
  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);
    }
  }

  /**
   * 

* 这里相对自动提交做个解说,如果设置自动提交为真,那么数据库将会将每一个SQL语句当做一个事务来执行,为了将多条SQL当做一个事务进行提交, * 必须将自动提交设置为false,然后进行手动提交。一般在我们的项目中,都需要将自动提交设置为false,即将自动提交关闭,使用手动提交

*

*  这个方法中通过对connection实例中的自动提交设置(真或假)进行判断,如果为false,表明不执行自动提交,则复位,重新将其设置为true。 * (自动提交的默认值为true)这个操作执行在connection关闭之前。可以看做是连接关闭之前的复位操作。 *

*/ 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. // mybatis 不会调用 提交/回滚 如果只是进行查找的连接 // 有些数据库读取事务时就开始事务了和授权了提交、回滚在关闭这个连接之前 // 一个解决方案是在关闭连接之前设置自动提交 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); } } } /** * 打开数据库连接,设置事务隔离等级,设置是否自动提交 * @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()); } setDesiredAutoCommit(autoCommit); } /** * 获取超时时长,该类并没有重写这个方法,直接返回null * @return * @throws SQLException */ @Override public Integer getTimeout() throws SQLException { return null; } }

ManagedTransaction

/**
 *    Copyright 2009-2017 the original author or authors.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */
package org.apache.ibatis.transaction.managed;

import java.sql.Connection;
import java.sql.SQLException;
import javax.sql.DataSource;

import org.apache.ibatis.logging.Log;
import org.apache.ibatis.logging.LogFactory;
import org.apache.ibatis.session.TransactionIsolationLevel;
import org.apache.ibatis.transaction.Transaction;

/**
 * {@link Transaction} that lets the container manage the full lifecycle of the transaction.
 * Delays connection retrieval until getConnection() is called.
 * Ignores all commit or rollback requests.
 * By default, it closes the connection but can be configured not to do it.
 * 译:
 * 该类让容器管理事务的完整生命周期。
 * 延迟连接恢复,直到得到连接(),忽略所有提交或者退回请求。
 * 默认情况下,它将关闭连接但不可以配置。;
 * 

*

* ManagedTransaction:MyBatis自身不会去实现事务管理,而是让程序的容器如(JBOSS,Weblogic)来实现对事务的管理 *

*
* @author Clinton Begin * * @see ManagedTransactionFactory */ public class ManagedTransaction implements Transaction { private static final Log log = LogFactory.getLog(ManagedTransaction.class); private DataSource dataSource; private TransactionIsolationLevel level; private Connection connection; 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 } /** * 关闭数据库连接,根据是否允许关闭连接closeConnection * @throws SQLException */ @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(); } } /** * 打开数据库连接,设置数据库隔离级别 * @throws SQLException */ 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; } }

你可能感兴趣的:(Mybatis-事务对象源码解析)