事务基础:请参看:http://www.cnblogs.com/solverpeng/p/5720306.html

一、Spring 事务管理

1.前提:事务管理器

在使用 Spring 声明式事务管理策略之前,必须配置事务管理器。

Spring 的核心事务管理器的顶级接口是 PlatformTransactionManager。

DataSourceTransactionManager:在应用程序中只需要处理一个数据源,而且通过 JDBC 进行存取。

HibernateTransactionManager:用 Hibernate 框架存取数据。

事务管理器以普通 Bean 的形式生命在 Spring IOC 容器中。如:

  1. <context:property-placeholder location="db.properties"/>
  2.  
  3. <bean class="com.mchange.v2.c3p0.ComboPooledDataSource" id="dataSource">
  4.   <property name="user" value="${jdbc.user}"/>
  5.   <property name="password" value="${jdbc.password}"/>
  6.   <property name="jdbcUrl" value="${jdbc.jdbcUrl}"/>
  7.   <property name="driverClass" value="${jdbc.DriverClass}"/>
  8. </bean>
  9.  
  10. <bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="transactionManager">
  11.   <property name="dataSource" ref="dataSource"/>
  12. </bean>

2.XML声明式事务管理:Spring 通过 SpringAOP 框架支持声明式事务。

(1)事务管理是一个横切关注点。

(2)具体操作:

<1>在 <beans> 根元素中添加  tx Schema 的约束。可以通过 tx  Schema 中定义的 <tx:advice> 元素声明事务增强。

  1. <tx:advice transaction-manager="transactionManager" id="txAdvice"/>

<2>将增强配置到相应的 Spring AOP 切面。

  1. <aop:config>
  2.   <aop:pointcut id="bookPointcut" expression="execution(* *.BookServiceImpl.*(..))"/>
  3.   <aop:advisor advice-ref="txAdvice" pointcut-ref="bookPointcut"/>
  4. </aop:config>

需要注意的是:只有公有的方法才可以添加增强。

3.注解声明式的管理事务:Spring 通过 @Transacational 注解声明式地管理事务

(1)Spring 允许使用 @Transacational 注解来标注事务方法。只能标注公有方法。

(2)可以在方法或类级别添加 @Transactional 注解。当添加到类上时,这个类的所有公有方法都会被定义成支持事务处理的。

(3)Spring Config 文件中的配置:

<1>只需要添加 <tx:annotation-driven/> 节点,并为其指定事务管理器就好了。

<2>指定事务管理器:若事务管理器名称是 transacationManager,就可以在 <tx:annotation-driven/> 节点中省略 transaction-manager 属性。

该元素会自动检测该名称的事务管理器。

  1. <context:property-placeholder location="db.properties"/>
  2.  
  3. <bean class="com.mchange.v2.c3p0.ComboPooledDataSource" id="dataSource">
  4.   <property name="user" value="${jdbc.user}"/>
  5.   <property name="password" value="${jdbc.password}"/>
  6.   <property name="jdbcUrl" value="${jdbc.jdbcUrl}"/>
  7.   <property name="driverClass" value="${jdbc.DriverClass}"/>
  8. </bean>
  9.  
  10. <bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="transactionManager">
  11.   <property name="dataSource" ref="dataSource"/>
  12. </bean>
  13.  
  14. <tx:annotation-driven/>

二、Spring 事务传播行为

1.JDBC 提供了事务隔离级别这种解决方案,Spring 对其进行了补充和扩展,就是 事务的传播行为。

2.Spring 提供了七种事务传播行为:

PROPAGATION_REQUIRED、PROPAGATION_REQUIRED_NEW、PROPAGATION_NESTED、PROPAGATION_SUPPORTS、PROPAGATION_NOT_SUPPORTED、PROPAGATION_NEVER、PROPAGATION_MANDATORY

我自己理解的 PROPAGATION_REQUIRED 和 PROPAGATION_REQUIRED_NEW :

方法 A 调用方法 B:

(1)如果 A 是一个事务方法,B 也是一个事务方法,那么 B 应该使用自己的事务还是 A 的事务?

如果使用 A 的事务 —— PROPAGATION_REQUIRED

如果使用 B 自己的事务 —— PROPAGATION_REQUIRED_NEW

举个例子来说明:

一个事务:A、B两位同学去饭馆吃饭

中午放学后,A 同学去饭馆吃饭,恰巧刚刚认识的 B 同学也在饭馆吃饭,A 同学是该自己吃呢?还是和 B 同学一起吃呢?

如果是和 B 一起 —— PROPAGATION_REQUIRED

如果是 A 自己吃 —— PROPAGATION_REQUIRED_NEW

(2)如果 A 是一个事务方法,B 不是一个事务方法,那么 B 会使用 A 的事务。

提示:PROPAGATION 意思是 传播

*上面是我自己的理解,没有将所有的情况覆盖,可能自己理解的也有偏差,看到此处的时候请小心求证。

(3)Spring 默认的事务传播行为为 PROPAGATION_REQUIRED

三、Spring 事务其他功能

除了强大的事务传播行为外,Spring 还提供了一些小的附加功能

1.事务超时——为了解决事务时间太长,消耗资源太多的问题,给事务设置一个最大时长,如果超时,则回滚事务。以 秒为单位。

2.只读事务——表示这个事务只读取数据而不更新数据

3.设置事务的回滚属性

默认情况下只检查运行时异常,会导致事务回滚。可以通过 rollbackFor 属性来定义,如果不止一种,可以通过 "," 进行分割。

不论是事务的传播行为还是事务的超时和只读属性,Spring 在 @Transactional 注解中提供了对应的属性。

也可以通过 XML 的方式去配置,如

  1. <tx:advice transaction-manager="transactionManager" id="bookAdvice">
  2.   <tx:attributes>
  3.     <tx:method name="shop" propagation="REQUIRED"/>
  4.   </tx:attributes>
  5. </tx:advice>

四、Spring 事务处理时,自我调用事务不生效。

问题描述:

  1. @Service
  2. public class PersonService {
  3. @Autowired
  4. private PersonDao personDao;
  5.  
  6. @Transactional
  7. public void outter() {
  8. for (int i = 1; i <= 10; i++) {
  9. this.inner(i);
  10. }
  11. }
  12.  
  13. @Transactional(propagation= Propagation.REQUIRES_NEW)
  14. public void inner(int index) {
  15. personDao.insert(index);
  16. if(index==3){
  17. int ii = 0;
  18. ii = 1/0;
  19. System.out.println(ii);
  20. }
  21. }
  22.  
  23. }

Spring Config 文件

  1. <context:component-scan base-package="com.nucsoft.spring"/>
  2. <context:property-placeholder location="classpath:db.properties"/>
  3.  
  4. <bean class="com.mchange.v2.c3p0.ComboPooledDataSource" id="dataSource">
  5. <property name="driverClass" value="${jdbc.driverClass}"/>
  6. <property name="jdbcUrl" value="${jdbc.jdbcUrl}"/>
  7. <property name="user" value="${jdbc.user}"/>
  8. <property name="password" value="${jdbc.password}"/>
  9. </bean>
  10.  
  11. <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
  12. <property name="dataSource" ref="dataSource"/>
  13. </bean>
  14.  
  15. <bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager" id="transactionManager">
  16. <property name="dataSource" ref="dataSource"/>
  17. </bean>
  18.  
  19. <tx:annotation-driven/>

测试:

  1. @Test
  2. public void testSupport() {
  3. PersonService bean = context.getBean(PersonService.class);
  4. bean.outter();
  5. }

结果:不论是将inner() 方法的 propagation 改为 Propagation.REQUIRED 还是 Propagation.REQUIRES_NEW,数据库中都没有插入数据。

分析:

因为 Spring 的事务管理是基于动态代理的,如果 target 中的方法不是被代理对象调用的,那么就不会织入切面代码,即事务不会生效。

对于上面的例子,在 outter() 方法中调用 inner() 方法的 this 是 PersonService 类对象。而不是 PersonService 的代理对象。

解决方案:

使用代理对象调用 inner() 方法。

具体做法:

(1)在 Spring Config 文件中添加如下配置:

<aop:aspectj-autoproxy expose-proxy="true"/>

说明:是否允许暴露代理对象。expose-proxy就是向ThreadLocal中存代理对象。

(2)手动的暴露代理对象。

  1. @Transactional
  2. public void outter() {
  3. for (int i = 1; i <= 10; i++) {
  4. ((PersonService) AopContext.currentProxy()).inner(i);
  5. }
  6. }
  7.  
  8. @Transactional(propagation= Propagation.REQUIRES_NEW)
  9. public void inner(int index) {
  10. personDao.insert(index);
  11. if(index==3){
  12. int ii = 0;
  13. ii = 1/0;
  14. System.out.println(ii);
  15. }
  16. }

说明:AopContext.currentProxy就是从ThreadLocal中取出代理对象。

参考的文章:

http://blog.csdn.net/derrantcm/article/details/46284811

http://jinnianshilongnian.iteye.com/blog/1487235

Spring应用——事务管理的更多相关文章

  1. Spring的事务管理

    事务 事务:是逻辑上一组操作,要么全都成功,要么全都失败. 事务特性(ACID) 原子性:事务不可分割 一致性:事务执行的前后,数据完整性保持一致 隔离性:一个事务执行的时候,不应该受到其他事务的打扰 ...

  2. spring笔记--事务管理之声明式事务

    事务简介: 事务管理是企业级应用开发中必不可少的技术,主要用来确保数据的完整性和一致性, 事务:就是一系列动作,它们被当作一个独立的工作单元,这些动作要么全部完成,要么全部不起作用. Spring中使 ...

  3. spring+mybatis事务管理

    spring+mybatis事务管理 最近在和朋友做一个项目,考虑用springmvc+mybatis来做,之前在公司工作吧,对于数据库这块的配置也有人再弄,最近因为这个项目,我就上网学习了一些关于数 ...

  4. spring,mybatis事务管理配置与@Transactional注解使用[转]

    spring,mybatis事务管理配置与@Transactional注解使用[转] spring,mybatis事务管理配置与@Transactional注解使用 概述事务管理对于企业应用来说是至关 ...

  5. Spring高级事务管理难点剖析

    1Spring事务传播行为 所谓事务传播行为就是多个事务方法相互调用时,事务如何在这些方法间传播.Spring支持7种事务传播行为 PROPAGATION_REQUIRED(加入已有事务) 如果当前没 ...

  6. CSDN上看到的一篇有关Spring JDBC事务管理的文章(内容比较全) (转)

    JDBC事务管理 Spring提供编程式的事务管理(Programmatic transaction manage- ment)与声明式的事务管理(Declarative transaction ma ...

  7. Spring之事务管理

        事务管理对于企业应用至关重要.它保证了用户的每一次操作都是可靠的,即便出现了异常的访问情况,也不至于破坏后台数据的完整性.     就像银行的自助取款机,通常都能正常为客户服务,但是也难免遇到 ...

  8. Mybatis整合Spring实现事务管理的源码分析

    一:前言 没有完整看完,但是看到了一些关键的地方,这里做个记录,过程会有点乱,以后逐渐补充最终归档为完整流程:相信看过框架源码的都知道过程中无法完全确定是怎样的流程,毕竟不可能全部都去测试一遍 ,但是 ...

  9. Hibernate与Spring的事务管理

    什么是事务 这个问题比较大,按照我的理解就是,一个事务内的n个操作,要么全部完成,一旦有一个操作有问题,那么所有的操作都全部回滚. Jdbc的事务 首先,大家已经知道了,事务说白了就是一个词----统 ...

随机推荐

  1. Mac Port 基本用法总结

    Mac Port 基本用法总结 Mac Port 基本用法总结 1. Mac Port的下载地址 http://www.macports.org/install.php 2. Mac Port的说明文 ...

  2. linux shell脚本备份mysql数据库

    #!/bin/sh # 备份数据库 # Mysql 用户名密码 MYSQL_USER=root MYSQL_PASS=root BACKUP_DIR=/data/backup/mysql DATA_D ...

  3. VS2010安装失败解决办法

    1. 运行regedit打开注册表: 2. 找到HKEY_LOCAL_MACHINE\SOFWARE\ Microsoft\ Internet Explorer\ MAIN: 3. MAIN子键的权限 ...

  4. appToken 来源

    .appToken的来源ActivityRecord, 用于在ActivityManagerService中记录Activity相关的信息(ActivityThread端 用的是ActivityCli ...

  5. CKEditor4.1和CKFinder2.3.1 for Mvc4最新 破解版,结合 打造"帅"的编辑器 For .Net

    CKEditor4.1+CKFinder2.3.1 FOR MVC4 最新破解版:(2013-3-23) baidu share: http://pan.baidu.com/share/link?sh ...

  6. Ajax学习笔记(二)

    二.prototype库具体解释 1.prototype库的使用 //导入下载好的prototype.js文件 <script type="text/javascript" ...

  7. JDBC性能分析与优化

    JDBC性能分析与优化V1.0http://www.docin.com/p-758600080.html

  8. “远程调试监视器(MSVSMON.EXE)似乎没有在远程计算机上运行“的完美解决方案

    今天调试程序时,Visual Studio突然报出了如下错误: Microsoft Visual Studio 远程调试监视器(MSVSMON.EXE)似乎没有在远程计算机上运行.这可能是因为防火墙阻 ...

  9. 【Xamarin报错】libpng warning : iCCP: Not recognizing known sRGB profile that has been edited

    报错: Xamarin Android 编译时发生以下错误: libpng warning : iCCP: Not recognizing known sRGB profile that has be ...

  10. 修改mysql默认字符集的方法

    +--------------------------+---------------------------------+ | Variable_name | Value | +---------- ...