此处先粘贴出Spring事务需要的配置内容:
1、Spring事务管理器的配置文件:

2、一个普通的JPA框架(此处是mybatis)的配置文件:

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
.....
</bean>

这两个里面都配置了datasource,而且这个datasource的对象是在Spring的容器里面。一下提几个问题:

            1、当JPA框架对数据库进行操作的时候,是从那里获取Connection?
            2、jdbc对事务的配置,比如事务的开启,提交以及回滚是在哪里设置的?
            3、Spring是通过aop拦截切面的所有需要进行事务管理的业务处理方法,那如何获取业务处理方法里面对数据库操作的事务呢?
           现在我来对上面的问题来一一回答
           1、这个问题很简单,既然在JPA的框架里面配置了datasource,那自然会从这个datasource里面去获得连接。
           2、jdbc的事务配置是在Connection对消里面有对应的方法,比如setAutoCommit,commit,rollback这些方法就是对事务的操作。
           3、Spring需要操作事务,那必须要对Connection来进行设置。Spring的AOP可以拦截业务处理方法,并且也知道业务处理方法里面的DAO操作的JAP框架是从datasource里面获取Connection对象,那么Spring需要对当前拦截的业务处理方法进行事务控制,那必然需要得到他内部的Connection对象。整体的结构图如下:
           

Spring 事务管理创造性的解决了很多以前要用重量级的应用服务器才能解决的事务问题,那么其实现原理一定很深奥吧?可是如果读者仔细研究了Spring事务管理的代码以后就会发现,事务管理其实也是如此简单的事情。这也印证了在本书开头的一句话“重剑无锋、大巧不工”,Spring并没有使用什么特殊的API,它运行的原理就是事务的原理。下面是DataSourceTransactionManager的启动事务用的代码(经简化):

protected void doBegin(Object transaction, TransactionDefinition definition)
{
DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
Connection con = null;
try
{
if (txObject.getConnectionHolder() == null)
{
Connection newCon = this.dataSource.getConnection();
txObject.setConnectionHolder(new ConnectionHolder(newCon), true);
}
txObject.getConnectionHolder().setSynchronizedWithTransaction(true);
con = txObject.getConnectionHolder().getConnection(); Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);
txObject.setPreviousIsolationLevel(previousIsolationLevel);
if (con.getAutoCommit())
{
txObject.setMustRestoreAutoCommit(true);
con.setAutoCommit(false);
}
txObject.getConnectionHolder().setTransactionActive(true);
// Bind the session holder to the thread.
if (txObject.isNewConnectionHolder())
{
TransactionSynchronizationManager.bindResource(getDataSource(),txObject.getConnectionHolder());
}
}
catch (SQLException ex)
{
DataSourceUtils.releaseConnection(con, this.dataSource);
throw new CannotCreateTransactionException( "Could not open JDBC Connection for transaction", ex);
}
}

在调用一个需要事务的组件的时候,管理器首先判断当前调用(即当前线程)有没有一个事务,如果没有事务则启动一个事务,并把事务与当前线程绑定。Spring使TransactionSynchronizationManager的bindResource方法将当前线程与一个事务绑定,采用的方式就是ThreadLocal,这可以从TransactionSynchronizationManager类的代码看出。

public abstract class TransactionSynchronizationManager
{
……
private static final ThreadLocal currentTransactionName = new ThreadLocal();
private static final ThreadLocal currentTransactionReadOnly = new ThreadLocal();
private static final ThreadLocal actualTransactionActive = new ThreadLocal(); ……
}

从doBegin的代码中可以看到在启动事务的时候,如果Connection是的自动提交的(也就是getAutoCommit()方法返回true)则事务管理就会失效,所以首先要调用setAutoCommit(false)方法将其改为非自动提交的。setAutoCommit(false)这个动作在有的JDBC驱动中会非常耗时,所以最好在配置数据源的时候就将“autoCommit”属性配置为true。

Spring 事务管理原理探究的更多相关文章

  1. Spring事务管理机制的实现原理-动态代理

    之前在做项目中遇到spring无法进行事务代理问题,最后发现是因为没有写接口,原因当时明白了,看到这篇文章写的清楚些,转过来 我们先来分析一下Spring事务管理机制的实现原理.由于Spring内置A ...

  2. Spring系列.事务管理原理简析

    Spring的事务管理功能能让我们非常简单地进行事务管理.只需要进行简单的两步配置即可: step1:开启事务管理功能 @Configuration //@EnableTransactionManag ...

  3. 【Java EE 学习 52】【Spring学习第四天】【Spring与JDBC】【JdbcTemplate创建的三种方式】【Spring事务管理】【事务中使用dbutils则回滚失败!!!??】

    一.JDBC编程特点 静态代码+动态变量=JDBC编程. 静态代码:比如所有的数据库连接池 都实现了DataSource接口,都实现了Connection接口. 动态变量:用户名.密码.连接的数据库. ...

  4. spring事务管理器设计思想(二)

    上文见<spring事务管理器设计思想(一)> 对于第二个问题,涉及到事务的传播级别,定义如下: PROPAGATION_REQUIRED-- 如果当前没有事务,就新建一个事务.这是最常见 ...

  5. Spring事务管理--多个ORM框架在使用时的情况分析

    公司的项目已经接近尾声了,总结一下项目中用到的技术,我发现项目中的有些东西还是挺模糊的,只是知道这么用就行了.并不清楚其中的原理.由于公司的项目比较老,是7年前的一个项目了,中间一直有人在维护,也是在 ...

  6. spring事务管理器设计思想(2)

    spring事务管理器设计思想(二) 上文见<spring事务管理器设计思想(一)> 对于第二个问题,涉及到事务的传播级别,定义如下: PROPAGATION_REQUIRED-- 如果当 ...

  7. Spring事务管理——回滚(rollback-for)控制

    探讨Spring事务控制中,异常触发事务回滚原理.文章进行了6种情况下的Spring事务是否回滚. 以下代码都是基于Spring与Mybatis整合,使用Spring声明式事务配置事务方法. 1.不捕 ...

  8. 阿里面试挂了,就因为面试官说我Spring 事务管理(器)不熟练?

    前言 事务管理,一个被说烂的也被看烂的话题,还是八股文中的基础股之一.但除了八股文中需要熟读并背诵的那些个传播行为之外,背后的"为什么"和核心原理更为重要. ​ 写这篇文章之前,我 ...

  9. Spring事务管理回滚问题

    Spring事务管理不能回滚问题 在前段时间学习SpringMVC的练习中,碰到声明式事务管理时,事务不能回滚的情况,通过查看博客和资料,解决了问题. 原因 导致Spring事务管理不能回滚的原因有两 ...

随机推荐

  1. PKU 1458 Common Subsequence(最长公共子序列,dp,简单)

    题目 同:ZJU 1733,HDU 1159 #include <stdio.h> #include <string.h> #include <algorithm> ...

  2. WPF中log4net的用法

    WPF中如何使用log4nethttp://www.cnblogs.com/C-Sharp2/archive/2013/04/12/WPF-LOG4NET.html Apache log4net Ma ...

  3. hdu 4474 Yet Another Multiple Problem

    题意: 找到一个n的倍数,这个数不能含有m个后续数字中的任何一个 题解: #include<stdio.h> #include<string.h> #include<qu ...

  4. AC题目简解-线段树

    线段树: http://www.notonlysuccess.com/index.php/segment-tree-complete/鉴于notonlysuccess大牛的博客对于题目的思路写的很简陋 ...

  5. win32 api ShouCursor 根据内部计数器 是否>= 0 决定是否 显示光标,每true时计数器+1,每false-1

    win32 api ShouCursor 根据内部计数器 是否>= 0 决定是否 显示光标,每true时计数器+1,每false-1,编程时true 和 false 的次数容易产生bug.

  6. C++:纯虚函数与抽象类

    5.4.3 纯虚函数和抽象类 纯虚函数是一个在基类中说明的虚函数,它在该基类中没有定义,但是要求在派生类中根据需要对它进行定义,或仍然说明为纯虚函数. 声明纯虚函数的一般格式是: virtual 函数 ...

  7. 查看Linux版本系统信息方法汇总

    Linux下如何查看版本信息, 包括位数.版本信息以及CPU内核信息.CPU具体型号等等,整个CPU信息一目了然.  1.# uname -a   (Linux查看版本当前操作系统内核信息)  Lin ...

  8. mapper device&lvm

    http://www.ibm.com/developerworks/cn/linux/l-devmapper/ http://baike.baidu.com/view/361916.htm?fr=al ...

  9. C++RAII

    http://baike.baidu.com/view/1120455.htm?fr=aladdin http://www.cnblogs.com/gnuhpc/archive/2012/12/04/ ...

  10. NDK(15)在ndk代码中注册和注销native函数

    转自:  http://www.cnblogs.com/canphp/archive/2012/11/13/2768937.html C和C++注册native函数的方式大致上相同,下面给出具体的代码 ...