MyBatis事务管理

MyBatis的事务管理是由TransactionFactoryTransaction两个接口定义的,TransactionFactory负责生成Transaction,这是一个典型的工厂模式。

官方提供了事务管理的两种模式:

  • Managed:对应ManagedTransactionFactoryManagedTransaction
  • JDBC:对应JdbcTransactionFactoryJdbcTransaction

重点看一下Transaction中提交和回滚的实现:

java 复制代码
public class ManagedTransaction implements Transaction {
  @Override
  public void commit() throws SQLException {
    // Does nothing
  }

  @Override
  public void rollback() throws SQLException {
    // Does nothing
  }
 }
java 复制代码
public class JdbcTransaction implements Transaction {
  @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();
    }
  }
}

可以看出,这两者的主要区别在于ManagedTransaction不会进行实际的事务提交和回滚,而是交由外部进行控制,而JdbcTransaction是我们能进行实际事务提交和回滚的,所以如果我们要手动控制事务,应该指定事务管理器为JdbcTransactionFactory,例如在mybatis的配置文件中:

xml 复制代码
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
  <environments default="development">
    <environment id="development">
      <transactionManager type="JDBC"/>
      <dataSource type="POOLED"></dataSource>
    </environment>
  </environments>
</configuration>

Transaction和实际执行查询的SqlSession又是什么关系呢?原来是创建SqlSession的时候会交由Executor管理,一起传给SqlSession

java 复制代码
public class DefaultSqlSessionFactory implements SqlSessionFactory {
  private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
    Transaction tx = null;
    try {
      final Environment environment = configuration.getEnvironment();
      final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
      tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
      final Executor executor = configuration.newExecutor(tx, execType);
      return new DefaultSqlSession(configuration, executor, autoCommit);
    } catch (Exception e) {
      closeTransaction(tx); // may have fetched a connection so lets call close()
      throw ExceptionFactory.wrapException("Error opening session.  Cause: " + e, e);
    } finally {
      ErrorContext.instance().reset();
    }
  }
}

当我们执行SqlSessioncommit()时,实际上是调用Executorcommit(),进而调用Transactioncommit()

java 复制代码
public class DefaultSqlSession implements SqlSession {
  @Override
  public void commit(boolean force) {
    try {
      executor.commit(isCommitOrRollbackRequired(force));
      dirty = false;
    } catch (Exception e) {
      throw ExceptionFactory.wrapException("Error committing transaction.  Cause: " + e, e);
    } finally {
      ErrorContext.instance().reset();
    }
  }
}
java 复制代码
public abstract class BaseExecutor implements Executor {
  @Override
  public void commit(boolean required) throws SQLException {
    if (closed) {
      throw new ExecutorException("Cannot commit, transaction is already closed");
    }
    clearLocalCache();
    flushStatements();
    if (required) {
      transaction.commit();
    }
  }
}
相关推荐
工程师老罗5 小时前
Image(图像)的用法
java·前端·javascript
leo_messi945 小时前
2026版商城项目(一)
java·elasticsearch·k8s·springcloud
globaldomain5 小时前
什么是用于长距离高速传输的TCP窗口扩展?
开发语言·网络·php
美味蛋炒饭.5 小时前
Tomcat 超详细入门教程(安装 + 目录 + 配置 + 部署 + 排错)
java·tomcat
沈阳信息学奥赛培训5 小时前
#undef 指令 (C/C++)
c语言·开发语言·c++
2401_873204655 小时前
分布式系统安全通信
开发语言·c++·算法
dreamxian5 小时前
苍穹外卖day11
java·spring boot·后端·spring·mybatis
Veggie266 小时前
【Java深度学习】PyTorch On Java 系列课程 第八章 17 :模型评估【AI Infra 3.0】[PyTorch Java 硕士研一课程]
java·人工智能·深度学习
weisian1516 小时前
Java并发编程--19-ThreadPoolExecutor七参数详解:拒绝Executors,手动掌控线程池
java·线程池·threadpool·七大参数
csdn5659738506 小时前
Java打包时,本地仓库有jar 包,Maven打包却还去远程拉取
java·maven·jar