Transaction

1. Transcation

在实践开发中,控制数据库事务是一件非常重要的工作,Mybatis使用Transaction接口对数据库事务进行了抽象,Transcation接口的定义如下:

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;

}

Transaction接口有JdbcTranscationManagedTranscation两个实现,其对象分别由JdbcTranscationFactoryManagedTranscationFactoy负责创建。这里也使用利用了工厂方法模式。

1.1. JdbcTranscation

JdbcTranscation依赖JDBC Connection控制事务的提交和回滚。JdbcTranscation中字段的含义如下所示:

  /**
   * 事务对应的数据库连接
   */
  protected Connection connection;
  /**
   * 数据库连接所属的DataSource
   */
  protected DataSource dataSource;
  /**
   * 事务的隔离级别
   */
  protected TransactionIsolationLevel level;
  /**
   * 是否自动提交
   */
  protected boolean autoCommit;

JdbcTranscation的构造方法有两个,分别是传递了Connection的,另一个没有传递的,代码如下所示:

  /**
   * 使用此构造方法,设置了除连接以外的值,至于connection字段的值,在调用{@link Transaction#getConnection()}的时候,
   * 调用到{@link DataSource#getConnection()}获取,
   *
   * 通过这种方式,Connection对象中设置的事务的隔离级别和是否自动提交属性,不会覆盖(除非为null)。
   * @param ds
   * @param desiredLevel
   * @param desiredAutoCommit
   */
  public JdbcTransaction(DataSource ds, TransactionIsolationLevel desiredLevel, boolean desiredAutoCommit) {
    dataSource = ds;
    level = desiredLevel;
    autoCommit = desiredAutoCommit;
  }

  /**
   * 使用此构造方法,事务的隔离级别和是否自动提交使用的都是Connection中的配置
   * @param connection
   */
  public JdbcTransaction(Connection connection) {
    this.connection = connection;
  }

这两者的区别在代码注释中也讲得很清楚了,下面是设计到创建JdbcTranscation对象涉及到的其他方法:

  @Override
  public Connection getConnection() throws SQLException {
    if (connection == null) {
      openConnection();
    }
    return connection;
  }
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);
  }

JdbcTranscation还有其他方法,例如:commit()rollback()等,都很简单,不在阐述。

1.2. ManagedTranscation

ManagedTranscation的实现更加简单,它同样依赖其中的dataSource字段获取连接,但其commit()rollback()方法都是空实现,事务的提交和回滚都要依赖容器管理的,ManagedTranscation通过closeConnection字段的值控制数据库连接的关闭行为。

2. TranscationFactory

TranscationFactory接口定义了配置新建TranscationFactory对象的方法,以及创建Transcation对象的方法,代码如下:

public interface TransactionFactory {

  /**
   * 配置TransactionFactory对象,一般紧跟着创建完成之后,完成对TransactionFactory的自定义配置
   * Sets transaction factory custom properties.
   * @param props
   */
  default void setProperties(Properties props) {
    // NOP
  }

  /**
   * 在指定的连接上创建Transaction对象
   * Creates a {@link Transaction} out of an existing connection.
   * @param conn Existing database connection
   * @return Transaction
   * @since 3.1.0
   */
  Transaction newTransaction(Connection conn);

  /**
   * 从指定数据源中获取数据库连接,并在此连接上创建Transaction对象
   * 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);

}

在实践中,Mybatis通常会与Spring继承使用,数据库的事务是交给Spring进行管理的,其中接口为SpringManagedTranscation



Mybatis源码分析   基础支持层      Mybatis源码分析

本博客所有文章除特别声明外,均采用 CC BY-SA 3.0协议 。转载请注明出处!