无关数据库事务的基础知识请翻看后面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来指定具体应用哪一种事务管理工厂:
<environments default="development"> <environment id="development"> <transactionManager type="JDBC"> <property name="..." value="..."/> </transactionManager> <dataSource type="POOLED"> <property name="driver" value="${driver}"/> <property name="url" value="${url}"/> <property name="username" value="${username}"/> <property name="password" value="${password}"/> </dataSource> </environment></environments>
通过transactionManager属性能够指定type=“JDBC”或者“MANAGED”,调配对应上述的JDBCTransactionFactory和ManagedTransactionFactory。
然而,如果你正在应用Spring + Mybatis,则SpringManagedTransactionFactory会笼罩掉以上两种设置。
Transaction
Mybatis的事务管制行为最终由Transaction实现,Transaction的接口定义非常简单:
public interface Transaction { Connection getConnection() throws SQLException; void commit() throws SQLException; void rollback() throws SQLException; void close() throws SQLException; Integer getTimeout() throws SQLException;}
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办法的其实是将connection交给连接池而并非真正的敞开,在偿还连接池之前复原其默认值应该也属于“最佳实际”的一种。
@Override public void close() throws SQLException { if (connection != null) { resetAutoCommit(); if (log.isDebugEnabled()) { log.debug("Closing JDBC Connection [" + connection + "]"); } connection.close(); } }
JDBCTransactoin其实属于手动管制事务的一种,目前利用应该非常少了。因为他相当于是在获取SqlSession的同时获取数据库连贯并开启了事务,而咱们利用中一个交易往往须要屡次执行数据库操作,也就会屡次获取SqlSession,因而也就不太容易通过JDBCTransactoin管制事务。
个别状况下咱们的我的项目还是要交给第三方事务管理器来实现事务管制,比方Spring的事务管理机制。
ManagedTransaction
MangedTransaction的实现就更简略了,因为他把事务管制交给了不出名的第三方,所以他齐全不论了。
除了获取和敞开链接外,事务的提交和回滚都是空架子,啥也不干:
@Override public void commit() throws SQLException { // Does nothing }
SpringManagedTransaction
如果应用Spring+Mybatis的话,Mybatis应用SpringManagedTransaction进行事务管制。
getConnection办法要借助DataSourceUtil的getConnection,咱们看一下DataSourceUtil曾经是在org.springframework.jdbc.datasource包下,阐明控制权曾经交给Spring了:
public static Connection getConnection(DataSource dataSource) throws CannotGetJdbcConnectionException { try { return doGetConnection(dataSource); } catch (SQLException ex) { throw new CannotGetJdbcConnectionException("Failed to obtain JDBC Connection", ex); } catch (IllegalStateException ex) { throw new CannotGetJdbcConnectionException("Failed to obtain JDBC Connection: " + ex.getMessage()); } }
调用了doGetConnection办法,其中呈现了咱们相熟的TransactionSynchronizationManager和ConnectionHolder:
public static Connection doGetConnection(DataSource dataSource) throws SQLException { Assert.notNull(dataSource, "No DataSource specified"); ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(dataSource); if (conHolder != null && (conHolder.hasConnection() || conHolder.isSynchronizedWithTransaction())) { conHolder.requested(); if (!conHolder.hasConnection()) { logger.debug("Fetching resumed JDBC Connection from DataSource"); conHolder.setConnection(fetchConnection(dataSource)); } return conHolder.getConnection(); }
具体能够参考后面无关Spring事务管制的相干文章。
commit和rollback的代码更简略:
@Override public void commit() throws SQLException { if (this.connection != null && !this.isConnectionTransactional && !this.autoCommit) { LOGGER.debug(() -> "Committing JDBC Connection [" + this.connection + "]"); this.connection.commit(); } }
工作原理是:以后connection与从Spring的ConnectionHolder中获取到的connection是否是同一对象(this.isConnectionTransactional==true),是的话则啥也不干(交给Spring的事务管理去干),不是的话就与JDBCTransaction一样、本人提交事务。
总结
Mybatis能够本人处理事务,也能够撒手不管、交给其余事务处理框架去解决。
Mybatis并非事务处理专家,绝大多数状况下Mybatis都是撒手不管的,把事务交给Spring等更加善于事务管理的框架去解决。
Spring事务管理相干内容请参考:https://segmentfault.com/a/11...
上一篇 Mybatis缓存机制