博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
mybaits源码分析(三) 事务管理
阅读量:4075 次
发布时间:2019-05-25

本文共 7152 字,大约阅读时间需要 23 分钟。

mybaits源码分析(三) 事务管理

前言:在mybaits源码分析(一) 核心执行流程事务这一块几乎是没讲到过。本篇主要讲解mybaits事务管理的实现机制,介绍mybaits事务设计接口和不同的实现,以及不同的事务实现JdbcTransaction 和 ManagedTransaction的具体实现不同,并且对mybaits配置文件解析,创建事务对象和实际使用的流程进行了分析。

一、概述:

        
       对数据库的事务而言,应该具有以下几点:创建(create)、提交(commit)、回滚(rollback)、关闭(close)。对应地,MyBatis将事务抽象成了Transaction接口,其接口定义如下:

    public interface Transaction {                  Connection getConnection() throws SQLException;                  void commit() throws SQLException;                  void rollback() throws SQLException;                  void close() throws SQLException;                }

 MyBatis的事务管理分为两种形式:

       1) 使用JDBC事务管理(JdbcTransaction),即用java.sql.Connection完成事务的创建、提交、回滚、关闭。
       2) 使用MANAGED事务管理(ManagedTransaction),这种机制MyBatis自身不会去实现事务管理,由提供数据源或链接的外层框架或容器实现。

二、事务相关类

1、主要类介绍

            Transaction : 事务接口
            TransactionFactory : 负责创建事务的工厂接口
            JdbcTransactionFactory : 负责创建jdbc事务的工厂
            JdbcTransaction:Jdbc事务实现
            ManagedTransactionFactory:负责创建Managed事务的工厂
            ManagedTransaction:Managed事务的实现

2、类图

3、JdbcTransaction的实现

       JdbcTransaction直接使用JDB的提交和回滚事务管理机制,它依赖于从dataSource中取得链接connection,connection对象获取被延迟到调用getConnection,如果autocommit设置为on,那么它会忽略commit和rollback。

        直观的讲,就是JdbcTransaction是使用java.sql.Connection的commit和rollback,JdbcTransaction相当于对java.sql.Connection的事务处理进行了一次包装,Transaction事务管理都是通过java.sql.Connection实现。

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();		    }		  }		 // ..... 省略		}

4、ManagedTransaction实现

    ManagedTransaction让容器来管理事务Transaction的整个生命周期,意思就是说,使用ManagedTransaction的commit和rollback功能不会对事务有任何的影响,它什么都不会做,它将事务管理的权利移交给了容器来实现。

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();		    }		  }

  三、事务相关配置加载

  1、配置文件

下面指定了一个mybaits的数据源的xml配置案例	  

 2、我们从解析environments节点查看过程

Mybaits根据配置文件指定的事务管理器的类型字符串type(JDBC or MANAGED),来决定创建不同的事务工厂类, 并且把创建的事务工厂TransactionFactory和数据源包装到Environment对象中。

private void environmentsElement(XNode context) throws Exception {			if (context != null) {				if (environment == null) {					environment = context.getStringAttribute("default"); // 默认的id				}				for (XNode child : context.getChildren()) {					String id = child.getStringAttribute("id"); 					if (isSpecifiedEnvironment(id)) { // 当前环境的配置						// 事务工厂  : 具体是根据transactionManager的type属性指定。						TransactionFactory txFactory = transactionManagerElement(child.evalNode("transactionManager"));						// 数据源工厂						DataSourceFactory dsFactory = dataSourceElement(child.evalNode("dataSource"));						DataSource dataSource = dsFactory.getDataSource();						Environment.Builder environmentBuilder = new Environment.Builder(id).transactionFactory(txFactory).dataSource(dataSource);						configuration.setEnvironment(environmentBuilder.build());					}				}			}		}

一个Configuration中只会创建一个Environment对象,一个Environment对象保存一个TransactionFactory和数据源。

四、事务对象的使用

上面讲了,我们解析配置,讲事务工厂类TransactionFactory和数据源包装到了Environment对象中,而Environment对象 是全局Configuration的一个属性,下面我们看看事务相关类的使用。

1、事务对象在那个时候创建? 

         我们知道创建一个SqlSession的时候,会对应的创建一个Executor,而Executor是我们实际执行增删改查的类,那么事务就是创建SqlSession的时候,包装到Executor内。我们直接看SqlSessionFactory的openSession的调用openSessionFromDataSource。

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);	      // 组装executor和configuration到DefaultSqlSession	      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();	    }	  }

 2、事务何时开启?如何提交回滚?

          如果我们需要开启事务,那么需要设置在创建SqlSession的使用,调用 SqlSessionFactory.openSession(flase), 底层调用的是JDBC的

    connection.setAutoCommit(desiredAutoCommit) 如果事务提交或回滚,我们调用SqlSessionFactory.close(),实际调用的是executor的close,然后executor会调用Trancation的close。

范例代码:	   SqlSession sqlSession = SqlSessionFactory.openSession(false);	   sqlSession.update('statementId',param);	   sqlSession.selectOne('queryStatementID',param);	   sqlSession.commit();	   sqlSession.close();

 

 

 

转载地址:http://cruni.baihongyu.com/

你可能感兴趣的文章
my read_university
查看>>
network manager
查看>>
OS + Linux Disk disk lvm / disk partition / disk mount / disk io
查看>>
RedHat + OS CPU、MEM、DISK
查看>>
net TCP/IP / TIME_WAIT / tcpip / iperf / cain
查看>>
webServer kzserver/1.0.0
查看>>
OS + Unix IBM Aix basic / topas / nmon / filemon / vmstat / iostat / sysstat/sar
查看>>
my ReadMap subway / metro / map / ditie / gaotie / traffic / jiaotong
查看>>
OS + Linux DNS Server Bind
查看>>
linux下安装django
查看>>
Android 解决TextView设置文本和富文本SpannableString自动换行留空白问题
查看>>
Android开发中Button按钮绑定监听器的方式完全解析
查看>>
Android自定义View实现商品评价星星评分控件
查看>>
postgresql监控工具pgstatspack的安装及使用
查看>>
postgresql查看表的和索引的情况,判断是否膨胀
查看>>
postgresql中根据oid和filenode去找表的物理文件的位置
查看>>
postgresql减少wal日志生成量的方法
查看>>
swift中单例的创建及销毁
查看>>
获取App Store中App的ipa包
查看>>
iOS 关于pods-frameworks.sh:permission denied报错的解决
查看>>