1.mybatis事务的配置和使用

mybatis事务有两种使用方式:

(a):使用JDBC的事务管理机制:即使用java.Sql.Connection对象完成对事务的提交,回滚和关闭操作。

(b):使用MANAGED的事务管理机制:mybatis本身不会去实现事务管理的相关操作,而是交个外部容器来管理事务。当与spring整合使用后,一般使用spring来管理事务。

在配置文件中的配置:

    <environments default="development">
<environment id="development">
//JDBC的事务方式
<transactionManager type="JDBC" />
<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 />,<dataSource>,<environment>。其中,<dataSource>节点封装了数据源的信息,<environment>封装了数据库的连接,包括数据源和事务,然后把该节点信息封装到了Configuration对象中,方便后面使用,现在看下mybatis在初始化加载配置文件时,对<environment/>节点的解析:

  private void environmentsElement(XNode context) throws Exception {
if (context != null) {
if (environment == null) {
environment = context.getStringAttribute("default");
}
for (XNode child : context.getChildren()) {
String id = child.getStringAttribute("id");
if (isSpecifiedEnvironment(id)) {
// 解析 <transactionManager>节点,获取事务工厂对象 进入该方法
TransactionFactory txFactory = transactionManagerElement(child.evalNode("transactionManager"));
// 解析<DataSource>节点,获取数据源对象
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());
}
}
}
}

进入解析<transactionManager/>节点的方法:

  private TransactionFactory transactionManagerElement(XNode context) throws Exception {
if (context != null) {
// 获取type的属性值,JDBC或者MANAGED
String type = context.getStringAttribute("type");
Properties props = context.getChildrenAsProperties();
//生成一个TransactionFactory实例
TransactionFactory factory = (TransactionFactory) resolveClass(type).newInstance();
factory.setProperties(props);
return factory;
}
throw new BuilderException("Environment declaration requires a TransactionFactory.");
}

2.事务工厂TransactionFactory

TransactionFactory定义了创建Transaction的两种方法,如下:

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
* 方法一:通过指定的Connection对象来创建事务
*/
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
* 方法二:通过DataSource,隔离级别,是否自动提交 来创建事务
*/
Transaction newTransaction(DataSource dataSource, TransactionIsolationLevel level, boolean autoCommit); }

TransactionFactory有两个子类:JdbcTransactionFactory和ManagedTransactionFactory

2.1 JdbcTransactionFactory,会创建JDBC类型的事务,就是JdbcTransaction,看下源码:

public class JdbcTransactionFactory implements TransactionFactory {

  public void setProperties(Properties props) {
}
// JDBCTransaction的创建有两种方法
public Transaction newTransaction(Connection conn) {
return new JdbcTransaction(conn);
} public Transaction newTransaction(DataSource ds, TransactionIsolationLevel level, boolean autoCommit) {
return new JdbcTransaction(ds, level, autoCommit);
}
}

2.2 ManagedTransactionFactory,会创建MANAGED类型的事务,ManagedTransaction,同样有两种方法:

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

3.JdbcTransaction和ManagedTransaction

 3.1 JdbcTransaction

从源码可知:jdbcTransaction从DataSource获取连接对象Connection,然后利用Connection对象管理事务的commit和rollback,实际在事务处理上,jdbcTransaction是对java.sql.Connection的一个包装,它是使用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;
}
// 使用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);
} }

3.2 ManagedTransaction 

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

mybatis事务管理机制详解的更多相关文章

  1. Spring事务管理(详解+实例)

    1 初步理解 理解事务之前,先讲一个你日常生活中最常干的事:取钱. 比如你去ATM机取1000块钱,大体有两个步骤:首先输入密码金额,银行卡扣掉1000元钱:然后ATM出1000元钱.这两个步骤必须是 ...

  2. (转)Spring事务管理(详解+实例)

    文章转自:http://blog.csdn.net/trigl/article/details/50968079 写这篇博客之前我首先读了<Spring in action>,之后在网上看 ...

  3. 《深入理解mybatis原理》 MyBatis事务管理机制

    MyBatis作为Java语言的数据库框架,对数据库的事务管理是其很重要的一个方面.本文将讲述MyBatis的事务管理的实现机制. 首先介绍MyBatis的事务Transaction的接口设计以及其不 ...

  4. 深入理解mybatis原理, Mybatis初始化SqlSessionFactory机制详解(转)

    文章转自http://blog.csdn.net/l454822901/article/details/51829785 对于任何框架而言,在使用前都要进行一系列的初始化,MyBatis也不例外.本章 ...

  5. MyBatis事务管理机制

    MyBatis作为Java语言的数据库框架,对数据库的事务管理是其非常重要的一个方面.   本文将讲述MyBatis的事务管理的实现机制,首先介绍MyBatis的事务Transaction的接口设计以 ...

  6. mybatis深入理解(三)-----MyBatis事务管理机制

    MyBatis作为Java语言的数据库框架,对数据库的事务管理是其非常重要的一个方面.本文将讲述MyBatis的事务管理的实现机制.首先介绍MyBatis的事务Transaction的接口设计以及其不 ...

  7. ARC内存管理机制详解

    ARC在OC里面个人感觉又是一个高大上的牛词,在前面Objective-C中的内存管理部分提到了ARC内存管理机制,ARC是Automatic Reference Counting---自动引用计数. ...

  8. object-c(oc)内存管理机制详解

    1.内存的创建和释放 让我们以Object-c世界中最最简单的申请内存方式展开,谈谈关于一个对象的生命周期.首先创建一个对象: 1 2 3 //“ClassName”是任何你想写的类名,比如NSStr ...

  9. spring的annotation-driven配置事务管理器详解

    http://blog.sina.com.cn/s/blog_8f61307b0100ynfb.html ——————————————————————————————————————————————— ...

随机推荐

  1. Automatically migrating data to new machines kafka集群扩充迁移topic

    The partition reassignment tool can be used to move some topics off of the current set of brokers to ...

  2. 【NOI2008】志愿者招募

    [NOI2008]志愿者招募 和[2017山东day7]养猫做法类似. 都是神仙题. 首先我设\(c_{i,j}=[l[j]\leq i\leq r[j]]\) ,于是就可以列出下面的不等式: \[ ...

  3. nginx相关命令

    https://www.cnblogs.com/zdz8207/p/CentOS-nginx-yum.html

  4. [小米 Online Judge]找出单独出现的数字

    描述: 给出N个数字.其中仅有一个数字出现过一次,其他数字均出现过两次,找出这个出现且只出现过一次的数字.要求时间和空间复杂度最小. 输入: 输入多个数字,每个数字以空格分开,回车结束 输出: 输出内 ...

  5. Python:Day53 Template基础

    一.模板由 html代码+逻辑控制代码 组成 二.逻辑控制代码的组成 1.变量(使用双大括号来引用变量) 语法格式:{{ var_name }} -----------------------Temp ...

  6. centos 6.9修改系统默认字符集

    [root@ckh ~]# locale –a #列出系统所支持的所有字符集 aa_DJ aa_DJ.iso88591 aa_DJ.utf8 aa_ER aa_ER@saaho aa_ER.utf8 ...

  7. Caused by: java.sql.SQLException: Value '0000-00-00 00:00:00' can not be represented as java.sql.Timestamp

    错误信息如下: Caused by: java.sql.SQLException: Value '0000-00-00 00:00:00' can not be represented as java ...

  8. Libinput 1.13 RC2发布

    Red Hat的Peter Hutterer周四宣布发布libinput 1.13 RC2,作为X.Org和Wayland Linux系统使用此输入处理库的最新测试版本. Libinput 1.13将 ...

  9. VMware 中安装虚拟机和宿主机通信

    网络上对于三种连接模式说的很多了,这里就不在具体的说明了.此处采用的NAT模式连接虚拟机,让虚拟机和宿主机互相通讯,并且让虚拟机能访问互联网. 1.首先设置虚拟机的网络,如下图.通过如下操作进入虚拟机 ...

  10. linux使用.net core 创建简单的MVC

    1 创建MVC 2.修改默认绑定的端口方法 ,在Program.cs 的Build之前加入 .UseUrls("http://*:8888")