数据库事务的基础知识请看之前Spring事务管理的文章。与Spring的事务管理相比,Mybatis的事务管理非常简单。底层结构首先熟悉与Mabtis交易或其底层结构相关的几个概念。TransactionFactory:事务工厂,Mybatis在进行数据库操作和获取SqlSession之前需要通过TransactionFactory获取事务管理器。Transaction:事务管理器,Mybatis最终通过Transaction完成对数据库操作的事务控制。TransactionFactory的配置从TransactionFactory的类图中可以看出Mybatis提供了3种不同的事务工厂:JDBCTransactionFactory:基于JDBC的事务工厂,负责创建JDBCTransaction。ManagedTransactionFactory:“托管事务工厂”,负责创建ManagedTransaction。SpringManagedTransactionFactory:Spring管理的事务工厂,负责创建SpringManagedTransaction。可以通过Mybatis的环境配置Environment指定使用哪个事务管理工厂:可以通过transactionManager属性指定type="JDBC"或"MANAGED",并赋值上面对应的JDBCTransactionFactory和ManagedTransactionFactory。但是,如果你使用的是Spring+Mybatis,SpringManagedTransactionFactory会覆盖上面的两个设置。TransactionMybatis的事务控制行为最终由Transaction完成。Transaction的接口定义很简单:publicinterfaceTransaction{ConnectiongetConnection()throwsSQLException;voidcommit()抛出SQLException;voidrollback()抛出SQLException;voidclose()抛出SQLException;IntegergetTimeout()throwsSQLException;}getConnection负责获取数据库连接,commit提交事务,rollback回滚事务,close关闭数据库连接,getTimeout获取事务超时设置。Mybatis的三种不同的事务管理器都需要实现Transaction接口的上述方法来实现事务控制。JDBCTransaction如果我们的项目将Mybatis事??务管理器配置为JDBC,那么Mybatis会使用JDBCTransaction来最终完成事务控制,其实就是上述Transaction接口的几个方法的实现。JDBCTransactoin的源码非常简单,一目了然。如果事务已经开启(数据库连接autoCommit=false),commit和rollback都直接调用数据库连接的commit和rollback方法完成事务的提交或回滚。close方法有点特殊,就是在关闭数据库连接之前,会调用一个resetAutoCommit()方法,将数据库连接的autoCommit设置为true(默认值)。其实这个动作是为了兼容连接池的配置。如果是池化的管理数据库连接,close方法其实是把连接交给连接池,而不是真正关闭。在返回连接池之前恢复其默认值也应该属于“最佳实践”。@Overridepublicvoidclose()throwsSQLException{if(connection!=null){resetAutoCommit();if(log.isDebugEnabled()){log.debug("关闭JDBC连接["+connection+"]");}connection.close();}}JDBCTransactoin其实是一种手动控制事务,目前应用应该很少。因为在获取SqlSession的同时相当于获取了数据库连接并开启了事务,而我们的应用中一个事务往往需要进行多次数据库操作,会多次获取SqlSession,所以不容易通过事务来控制JDBC事务处理。一般情况下,我们的项目还是需要交给第三方事务管理器来实现事务控制,比如Spring的事务管理机制。ManagedTransactionMangedTransaction的实现就更简单了,因为他把事务控制权交给了一个不知名的第三方,所以他就完全忽略了。除了获取和关闭链接,事务的提交和回滚都是空架子,什么都不做:@Overridepublicvoidcommit()throwsSQLException{//Doesnothing}SpringManagedTransaction如果使用Spring+Mybatis,Mybatis使用SpringManagedTransaction进行交易控制。getConnection方法需要用到DataSourceUtil的getConnection。我们看到DataSourceUtil已经在org.springframework.jdbc.datasource包下了,说明控制权已经交给了Spring:}catch(SQLExceptionex){thrownewCannotGetJdbcConnectionException("无法获取JDBC连接",ex);}catch(IllegalStateExceptionex){thrownewCannotGetJdbcConnectionException("无法获取JDBC连接:"+ex.getMessage());}}doGetConnection方法被调用,熟悉的TransactionSynchronizationManager和ConnectionHolder出现了:ConnectionHolderconHolder=(ConnectionHolder)TransactionManSynchronization.getResourcee(数据源);if(conHolder!=null&&(conHolder.hasConnection()||conHolder.isSynchronizedWithTransaction())){conHolder.requested();if(!conHolder.hasConnection()){logger.debug("从数据源获取恢复的JDBC连接");conHolder.setConnection(fetchConnection(dataSource));}返回conHolder.getConnection();}详细可以参考之前关于Spring事务控制的相关文章。提交和回滚的代码更简单:@Overridepublicvoidcommit()throwsSQLException{if(this.connection!=null&&!this.isConnectionTransactional&&!this.autoCommit){LOGGER.debug(()->"CommittingJDBC连接["+this.connection+"]");这个.connection.commit();工作原理是:当前连接和从Spring的ConnectionHolder获取的连接是否是同一个对象(this.isConnectionTransactional==true),如果是,则什么也不做(交给Spring事务管理),如果不是,则为和JDBCTransaction一样,自己提交事务。总结一下,Mybatis可以自己处理事务,也可以不管事务,交给其他事务处理框架处理。Mybatis不是事务处理方面的专家。大部分情况下,Mybatis都不管了,事务交给Spring等更擅长事务管理的框架。Spring事务管理相关内容可参考:https://segmentfault.com/a/11...上一篇Mybatis缓存机制下一篇MybatisMapper代理对象生成及调用流程