mybatis 源码系列 组件之 Transaction
来源:互联网 发布:淘宝卖家基本设置出错 编辑:程序博客网 时间:2024/04/30 10:50
Question:
. mybatis 对事务做了什么样的封装?
. mybatis 支持的 jdbc 和 managed transaction如何实现?
事务对于数据库应用而言,是一个很重要的环节,一般有 提交,回滚 机制,同时,mybatis 抽象出了如下 事务原型:
/** * Wraps a database connection. * Handles the connection lifecycle that comprises: its creation, preparation, commit/rollback and close. * * @author Clinton Begin */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;}
一、使用JDBC的事务管理机制:即利用java.sql.Connection对象完成对事务的提交(commit())、回滚(rollback())、关闭(close())等
二、使用MANAGED的事务管理机制:这种机制MyBatis自身不会去实现事务管理,而是让程序的容器如(JBOSS,Weblogic)来实现对事务的管理,包括 rollback 和 commit 动作
顺便看看 ManagedTransaction 的实现: 可以知道,其不会在rollback 和 commit中做任何事情,
/** * {@link Transaction} that lets the container manage the full lifecycle of the transaction. * Delays connection retrieval until getConnection() is called. * Ignores all commit or rollback requests. * By default, it closes the connection but can be configured not to do it. * * @see ManagedTransactionFactory *//** * @author Clinton Begin */public class ManagedTransaction implements Transaction { private static final Log log = LogFactory.getLog(ManagedTransaction.class); private DataSource dataSource; private TransactionIsolationLevel level; private Connection connection; private boolean closeConnection; public ManagedTransaction(Connection connection, boolean closeConnection) { this.connection = connection; this.closeConnection = closeConnection; } public ManagedTransaction(DataSource ds, TransactionIsolationLevel level, boolean closeConnection) { this.dataSource = ds; this.level = level; this.closeConnection = closeConnection; } public Connection getConnection() throws SQLException { if (this.connection == null) { openConnection(); } return this.connection; } public void commit() throws SQLException { // Does nothing } public void rollback() throws SQLException { // Does nothing } public void close() throws SQLException { if (this.closeConnection && this.connection != null) { if (log.isDebugEnabled()) { log.debug("Closing JDBC Connection [" + this.connection + "]"); } this.connection.close(); } } protected void openConnection() throws SQLException { if (log.isDebugEnabled()) { log.debug("Opening JDBC Connection"); } this.connection = this.dataSource.getConnection(); if (this.level != null) { this.connection.setTransactionIsolation(this.level.getLevel()); } }}
/** * {@link Transaction} that makes use of the JDBC commit and rollback facilities directly. * It relies on the connection retrieved from the dataSource to manage the scope of the transaction. * Delays connection retrieval until getConnection() is called. * Ignores commit or rollback requests when autocommit is on. * * @see JdbcTransactionFactory *//** * @author Clinton Begin */public class JdbcTransaction implements Transaction { private static final Log log = LogFactory.getLog(JdbcTransaction.class); 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()) { if (log.isDebugEnabled()) { log.debug("Committing JDBC Connection [" + connection + "]"); } connection.commit(); } } public void rollback() throws SQLException { if (connection != null && !connection.getAutoCommit()) { if (log.isDebugEnabled()) { log.debug("Rolling back JDBC Connection [" + connection + "]"); } connection.rollback(); } } public void close() throws SQLException { if (connection != null) { resetAutoCommit(); if (log.isDebugEnabled()) { log.debug("Closing JDBC Connection [" + connection + "]"); } connection.close(); } } protected void setDesiredAutoCommit(boolean desiredAutoCommit) { try { if (connection.getAutoCommit() != desiredAutoCommit) { if (log.isDebugEnabled()) { log.debug("Setting autocommit to " + desiredAutoCommit + " on JDBC Connection [" + connection + "]"); } connection.setAutoCommit(desiredAutoCommit); } } catch (SQLException e) { // Only a very poorly implemented driver would fail here, // and there's not much we can do about that. throw new TransactionException("Error configuring AutoCommit. " + "Your driver may not support getAutoCommit() or setAutoCommit(). " + "Requested setting: " + desiredAutoCommit + ". Cause: " + e, e); } } protected void resetAutoCommit() { try { if (!connection.getAutoCommit()) { // MyBatis does not call commit/rollback on a connection if just selects were performed. // Some databases start transactions with select statements // and they mandate a commit/rollback before closing the connection. // A workaround is setting the autocommit to true before closing the connection. // Sybase throws an exception here. if (log.isDebugEnabled()) { log.debug("Resetting autocommit to true on JDBC Connection [" + connection + "]"); } connection.setAutoCommit(true); } } catch (SQLException e) { log.debug("Error resetting autocommit to true " + "before closing the connection. Cause: " + e); } } protected void openConnection() throws SQLException { if (log.isDebugEnabled()) { log.debug("Opening JDBC Connection"); } connection = dataSource.getConnection(); if (level != null) { connection.setTransactionIsolation(level.getLevel()); } setDesiredAutoCommit(autoCommmit); }}
为了方便建立事务,mybatis提供了 事务工厂,同时 就两种事务管理机制,分别由 具体的 工厂类来实现:
如下为 TransactionFactory 接口
/** * Creates {@link Transaction} instances. * * @author Clinton Begin */public interface TransactionFactory { /** * Sets transaction factory custom properties. * @param props */ void setProperties(Properties props); /** * Creates a {@link Transaction} out of an existing connection. * @param conn Existing database connection * @return Transaction * @since 3.1.0 */ Transaction newTransaction(Connection conn); /** * 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);}
public class ManagedTransactionFactory implements TransactionFactory { private boolean closeConnection = true; public void setProperties(Properties props) { if (props != null) { String closeConnectionProperty = props.getProperty("closeConnection"); if (closeConnectionProperty != null) { closeConnection = Boolean.valueOf(closeConnectionProperty); } } } public Transaction newTransaction(Connection conn) { return new ManagedTransaction(conn, closeConnection); } public Transaction newTransaction(DataSource ds, TransactionIsolationLevel level, boolean autoCommit) { // Silently ignores autocommit and isolation level, as managed transactions are entirely // controlled by an external manager. It's silently ignored so that // code remains portable between managed and unmanaged configurations. return new ManagedTransaction(ds, level, closeConnection); }}
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); }}
0 0
- mybatis 源码系列 组件之 Transaction
- mybatis 源码系列 组件之 logging
- mybatis 源码系列 组件之 cache
- mybatis 源码系列 组件之 io
- mybatis 源码系列 组件之 plugin
- mybatis 源码系列 组件之 reflection
- mybatis 源码系列 组件之 datasource
- MySQL系列:innodb源码分析之mini transaction
- MySQL系列:innodb源码分析之mini transaction
- MySQL系列:innodb源码分析之mini transaction
- Mybatis源码分析系列
- sharding-jdbc源码阅读之soft transaction
- Mybatis 源码系列 相关资料
- 深入浅出Mybatis系列(三)---配置详解之properties与environments(mybatis源码篇)
- 深入浅出Mybatis系列(四)---配置详解之typeAliases别名(mybatis源码篇)
- 深入浅出Mybatis系列(三)---配置详解之properties与environments(mybatis源码篇)
- 深入浅出Mybatis系列(三)---配置详解之properties与environments(mybatis源码篇)
- 深入浅出Mybatis系列(四)---配置详解之typeAliases别名(mybatis源码篇)
- pat(B) 1002. 写出这个数
- UE4发报机-关卡蓝图调用蓝图类的发报机
- [Android]Volley在没有网络时读取图片缓存时出现的问题
- LDS文件格式分析
- x86架构和arm架构处理器分析
- mybatis 源码系列 组件之 Transaction
- 百度编辑器多图上传返回图片绝对路径问题
- Oracle 表连接 导致排序错乱
- vi的复制粘贴命令
- linux 信号signal和sigaction理解
- Andoid之——缓存杂项
- 加载指定包名下的所有类或根据类的annotation进行过滤的工具类
- Kth Largest Element in an Array
- Shell Script - 追踪与debug