MyBatis教程大全


 MyBatis SQL 映射

     MyBatis select 标签

     MyBatis 多数据库支持

     MyBatis selectKey 标签作用

     MyBatis @SelectKey注解用法介绍

     MyBatis @SelectKey注解用法详细介绍

     MyBatis keyProperty 属性介绍

     MyBatis insert、update 和 delete 元素

     MyBatis sql 元素

 MyBatis SQL 参数映射

     MyBatis SQL 参数映射

 MyBatis 动态SQL

     MyBatis 动态SQL与数据准备

     MyBatis if 标签

     MyBatis if else 用法

     MyBatis choose、when、otherwise 标签

     MyBatis where 标签

     MyBatis set 标签

     MyBatis foreach 标签

     MyBatis bind 标签

     MyBatis trim 标签

 MyBatis SQL 结果映射

 MyBatis SQL 结果之关系映射

 MyBatis 使用介绍

     MyBatis typeAliases 类型别名

     MyBatis typeHandlers 类型处理器

     MyBatis Transaction 事务接口

     MyBatis transactionManager 事务管理

     SqlSessionFactory 介绍

     MyBatis 核心对象 SqlSession

     MyBatis 初始化 创建 Session 实例

     MyBatis ObjectFactory 对象工厂

     MyBatis缓存机制:一级缓存和二级缓存

     MyBatis 常用注解

 MyBatis 配置文件

     MyBatis 配置文件

 MyBatis 映射

     MyBatis 映射简介

     MyBatis ResultMap 映射

     MyBatis 自动映射

     MyBatis 高级映射

     MyBatis 集合映射

     MyBatis 关联映射

     MyBatis 一对一关联映射

     MyBatis 一对多关联映射

     MyBatis 多对多关联映射

     MyBatis 一对一(注解形式)

     MyBatis 一对多(注解形式)

     MyBatis 多对多(注解形式)

     MyBatis resultMap 元素

 MyBatis 面试题库

     #{}和${}的区别是什么?

     数据库链接中断如何处理?

     数据库插入重复如何处理?

     事务执行过程中宕机的应对处理方式

     Java客户端中的一个Connection问题

MyBatis transactionManager 事务管理

1、MyBatis事务配置

在MyBatis的配置文件中可以配置事务管理方式如下:

<?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
 <configuration>
     <environments default="development">
          <environment id="development">
              <!--配置事务的管理方式-->
              <transactionManager type="JDBC" />
              <!-- 配置数据库连接信息 -->
              <dataSource type="POOLED">
                  <property name="driver" value="com.mysql.jdbc.Driver" />
                 <property name="url" value="jdbc:mysql://localhost:3306/mybatis" />
                 <property name="username" value="root" />
                 <property name="password" value="root" />
             </dataSource>
         </environment>
     </environments>    
 </configuration>

说明:
(1)type为"JDBC"时,使用JdbcTransaction管理事务。
(2)type为"managed"时,使用ManagedTransaction管理事务(也就是交由外部容器管理)

2、MyBatis事务工厂

mybatis的事务是由TransactionFactory创建的,利用典型的简单工厂模式来创建Transaction,如下图:

transaction-factory.jpg

说明:

  • Transaction:封装事务管理方法的接口
  • TransactionFactory:抽象事务工厂生产方法
  • JdbcTransactionFactory:实现TransactionFactory接口,用于生产JdbcTransaction的工厂类
  • ManagedTransactionFactory:实现TransactionFactory接口,用于生产ManagedTransaction的工厂类
  • JdbcTransaction:实现Transaction接口,只是对事务进行了一层包装、实际调用数据库连接Connection的事务管理方法
  • ManagedTransaction:实现Transaction没有对数据库连接做任何事务处理、交由外部容器管理

3、MyBatis事务源码分析

第一步:解析配置文件的transactionManager节点。

private void environmentsElement(XNode context) throws Exception {
          //只关注事务部分...
          TransactionFactory txFactory = transactionManagerElement(child.evalNode("transactionManager"));
          ...
  }
  
private TransactionFactory transactionManagerElement(XNode context) throws Exception {
    if (context != null) {
      String type = context.getStringAttribute("type");
      Properties props = context.getChildrenAsProperties();
      TransactionFactory factory = (TransactionFactory) resolveClass(type).newInstance();
      factory.setProperties(props);
      return factory;
    }
    throw new BuilderException("Environment declaration requires a TransactionFactory.");
  }

注意:两种事务工厂已经在mybatis初始化的时候完成了注册:
typeAliasRegistry.registerAlias("JDBC", JdbcTransactionFactory.class);
typeAliasRegistry.registerAlias("MANAGED", ManagedTransactionFactory.class);

第二步:利用反射机制生成具体的的factory,此处以JdbcTransactionFactory为例,查看一下JdbcTransactionFactory的源码:

public class JdbcTransactionFactory implements TransactionFactory {

  public void setProperties(Properties props) {
  }

  public Transaction newTransaction(Connection conn) {
    return new JdbcTransaction(conn);
  }

  public Transaction newTransaction(DataSource ds, TransactionIsolationLevel level, boolean autoCommit) {
    return new JdbcTransaction(ds, level, autoCommit);
  }
}

说明:在反射过程中,JdbcTransactionFactory默认无参构造方法被调用

第三步:获取具体类型的事务,以JdbcTransaction为例。

public Transaction newTransaction(Connection conn) {
    return new JdbcTransaction(conn);
  }

说明:JdbcTransaction是通过Connection来创建具体的实例

第四步:事务的底层实现。以JdbcTransaction为例来说明。

public class JdbcTransaction implements Transaction
{

    /* 连接**/
    protected Connection connection;

    /* 数据源**/
    protected DataSource dataSource;

    /* 事务等级**/
    protected TransactionIsolationLevel level;

    /* 事务提交**/
    protected boolean autoCommmit;

    public JdbcTransaction(DataSource ds, TransactionIsolationLevel desiredLevel, boolean desiredAutoCommit)
    {
        dataSource = ds;
        level = desiredLevel;
        autoCommmit = desiredAutoCommit;
    }

    public JdbcTransaction(Connection connection)
    {
        this.connection = connection;
    }

    public Connection getConnection() throws SQLException
    {
        if (connection == null)
        {
            openConnection();
        }
        //返回连接
        return connection;
    }

    public void commit() throws SQLException
    {
        if (connection != null && !connection.getAutoCommit())
        {
            //连接提交
            connection.commit();
        }
    }

    public void rollback() throws SQLException
    {
        if (connection != null && !connection.getAutoCommit())
        {
            //操作回滚
            connection.rollback();
        }
    }

    public void close() throws SQLException
    {
        if (connection != null)
        {
            resetAutoCommit();

            //关闭连接
            connection.close();
        }
    }

    protected void setDesiredAutoCommit(boolean desiredAutoCommit)
    {
        try
        {
            //事务提交状态不一致时修改
            if (connection.getAutoCommit() != desiredAutoCommit)
            {
                connection.setAutoCommit(desiredAutoCommit);
            }
        }
        catch (SQLException e)
        {
            throw new TransactionException("Error configuring AutoCommit.", e);
        }
    }

    protected void resetAutoCommit()
    {
        try
        {
            if (!connection.getAutoCommit())
            {

                connection.setAutoCommit(true);
            }
        }
        catch (SQLException e)
        {

        }
    }

    protected void openConnection() throws SQLException
    {

        connection = dataSource.getConnection();
        if (level != null)
        {
            connection.setTransactionIsolation(level.getLevel());
        }
        setDesiredAutoCommit(autoCommmit);
    }

}

从源码中可知,JdbcTransaction如何管理事务的,是通过封装调用DataSource获取connection来实现的。