`

事物管理,spring事物详解,spring @transactional

阅读更多
对于spring @transactional标签的使用时出现意料之外的错误,数据不同步。后来详细研究spring的事物机制和回滚的触发时机得到解决。以下资料收集于网络:


1.声明式事务配置
* 配置SessionFactory
* 配置事务管理器
* 事务的传播特性
* 那些类那些方法使用事务
2、编写业务逻辑方法
* 继承HibernateDaoSupport类,使用HibernateTemplate来持久化,HibernateTemplate是 Hibernate Session的轻量级封装
* 默认情况下运行期异常才会回滚(包括继承了RuntimeException子类),普通异常是不会滚的
* 编写业务逻辑方法时,最好将异常一直向上抛出,在表示层(struts)处理
* 关于事务边界的设置,通常设置到业务层,不要添加到Dao上 
3、了解事务的几种传播特性
1. PROPAGATION_REQUIRED: 如果存在一个事务,则支持当前事务。如果没有事务则开启
2. PROPAGATION_SUPPORTS: 如果存在一个事务,支持当前事务。如果没有事务,则非事务的执行
3. PROPAGATION_MANDATORY: 如果已经存在一个事务,支持当前事务。如果没有一个活动的事务,则抛出异常。
4. PROPAGATION_REQUIRES_NEW: 总是开启一个新的事务。如果一个事务已经存在,则将这个存在的事务挂起。
5. PROPAGATION_NOT_SUPPORTED: 总是非事务地执行,并挂起任何存在的事务。
6. PROPAGATION_NEVER: 总是非事务地执行,如果存在一个活动事务,则抛出异常
7. PROPAGATION_NESTED:如果一个活动的事务存在,则运行在一个嵌套的事务中. 如果没有活动事务,
     则按TransactionDefinition.PROPAGATION_REQUIRED 属性执行
4、Spring事务的隔离级别
1. ISOLATION_DEFAULT: 这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别.
     另外四个与JDBC的隔离级别相对应
2. ISOLATION_READ_UNCOMMITTED: 这是事务最低的隔离级别,它充许令外一个事务可以看到这个事务未提交的数据。
     这种隔离级别会产生脏读,不可重复读和幻像读。
3. ISOLATION_READ_COMMITTED: 保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据
4. ISOLATION_REPEATABLE_READ: 这种事务隔离级别可以防止脏读,不可重复读。但是可能出现幻像读。
     它除了保证一个事务不能读取另一个事务未提交的数据外,还保证了避免下面的情况产生(不可重复读)。
5. ISOLATION_SERIALIZABLE 这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行。
     除了防止脏读,不可重复读外,还避免了幻像读。   


  * 事务隔离:当前事务和其它事务的隔离的程度。例如,这个事务能否看到其他事务未提交的写数据?
  * 事务传播:通常在一个事务中执行的所有代码都会在这个事务中运行。但是,如果一个事务上下文已经存在,有几个选项可以指定一个事务性方法的执行行为:例如,简单地在现有的事务中继续运行(大多数情况);或者挂起现有事务,创建一个新的事务。Spring提供EJB CMT中常见的事务传播选项。
  * 事务超时: 事务在超时前能运行多久(自动被底层的事务基础设施回滚)。
  * 只读状态: 只读事务不修改任何数据。只读事务在某些情况下(例如当使用Hibernate时),是一种非常有用的优化。
* 回滚规则的概念比较重要:它使我们能够指定什么样的异常(和throwable)将导致自动回滚。我们在配置文件中声明式地指定,无须在Java代码中。同时,我们仍旧可以通过调用 TransactionStatus 的 setRollbackOnly() 方法编程式地回滚当前事务。通常,我们定义一条规则,声明 MyApplicationException 必须总是导致事务回滚。这种方式带来了显著的好处,它使你的业务对象不必依赖于事务设施。典型的例子是你不必在代码中导入Spring API,事务等。
* 在理解Spring的声明式事务管理方面最重要的概念是:Spring的事务管理是通过AOP代理实现的。其中的事务通知由元数据(目前基于XML或注解)驱动。代理对象与事务元数据结合产生了一个AOP代理,它使用一个PlatformTransactionManager实现品配合TransactionInterceptor,在方法调用前后实施事务。
*
* Spring框架的事务基础架构代码将默认地 只 在抛出运行时和unchecked exceptions时才标识事务回滚。 也就是说,当抛出一个 RuntimeException 或其子类例的实例时。(Errors 也一样 - 默认地 - 标识事务回滚。)从事务方法中抛出的Checked exceptions将 不 被标识进行事务回滚。
* 就是这些默认的设置;严格规定了哪些 Exception 类型将被标识进行事务回滚。
  默认的 <tx:advice/> 设置如下:
  * 事务传播设置是 REQUIRED
  * 隔离级别是 DEFAULT
  * 事务是 读/写
  * 事务超时默认是依赖于事务系统的,或者事务超时没有被支持。
  * 任何 RuntimeException 将触发事务回滚,但是任何 checked Exception 将不触发事务回滚




  Table?9.1.?<tx:method/> 有关的设置
属性是否需要?默认值描述name是?   与事务属性关联的方法名。通配符(*)可以用来指定一批关联到相同的事务属性的方法。 如:'get*'、'handle*'、'on*Event'等等。 propagation不REQUIRED事务传播行为isolation不DEFAULT事务隔离级别timeout不-1事务超时的时间(以秒为单位)read-only不false事务是否只读?rollback-for不?   将被触发进行回滚的 Exception(s);以逗号分开。 如:'com.foo.MyBusinessException,ServletException' no-rollback-for不?   不 被触发进行回滚的 Exception(s);以逗号分开。 如:'com.foo.MyBusinessException,ServletException'


事务回滚陷阱

清单 1. 没有回滚支持

@Transactional(propagation=Propagation.REQUIRED)
public TradeData placeTrade(TradeData trade) throws Exception {
   try {
      insertTrade(trade);
      updateAcct(trade);
      return trade;
   } catch (Exception up) {
      //log the error
      throw up;
   }
}


假设帐户中没有足够的资金来购买需要的股票,或者还没有准备购买或出售股票,并抛出了一个受控异常(例如 FundsNotAvailableException),那么交易订单会保存在数据库中吗?还是整个逻辑工作单元将执行回滚?答案出乎意料:根据受控异常(不管是在 Spring Framework 中还是在 EJB 中),事务会提交它还未提交的所有工作。使用清单 13,这意味着,如果在执行 updateAcct() 方法期间抛出受控异常,就会保存交易订单,但不会更新帐户来反映交易情况。

这可能是在使用事务时出现的主要数据完整性和一致性问题了。运行时异常(即非受控异常)自动强制执行整个逻辑工作单元的回滚,但受控异常不会。因此,清单 13 中的代码从事务角度来说毫无用处;尽管看上去它使用事务来维护原子性和一致性,但事实上并没有。

尽管这种行为看起来很奇怪,但这样做自有它的道理。首先,不是所有受控异常都是不好的;它们可用于事件通知或根据某些条件重定向处理。但更重要的是,应用程序代码会对某些类型的受控异常采取纠正操作,从而使事务全部完成。例如,考虑下面一种场景:您正在为在线书籍零售商编写代码。要完成图书的订单,您需要将电子邮件形式的确认函作为订单处理的一部分发送。如果电子邮件服务器关闭,您将发送某种形式的 SMTP 受控异常,表示邮件无法发送。如果受控异常引起自动回滚,整个图书订单就会由于电子邮件服务器的关闭全部回滚。通过禁止自动回滚受控异常,您可以捕获该异常并执行某种纠正操作(如向挂起队列发送消息),然后提交剩余的订单。

使用 Declarative 事务模式(本系列的第 2 部分将进行更加详细的描述)时,必须指定容器或框架应该如何处理受控异常。在 Spring Framework 中,通过 @Transactional 注释中的 rollbackFor 参数进行指定,如清单 2所示:


清单 2. 添加事务回滚支持 — Spring

@Transactional(propagation=Propagation.REQUIRED, rollbackFor=Exception.class)
public TradeData placeTrade(TradeData trade) throws Exception {
   try {
      insertTrade(trade);
      updateAcct(trade);
      return trade;
   } catch (Exception up) {
      //log the error
      throw up;
   }
}


注意,@Transactional 注释中使用了 rollbackFor 参数。这个参数接受一个单一异常类或一组异常类,您也可以使用 rollbackForClassName 参数将异常的名称指定为 Java String 类型。还可以使用此属性的相反形式(noRollbackFor)指定除某些异常以外的所有异常应该强制回滚。通常大多数开发人员指定 Exception.class 作为值,表示该方法中的所有异常应该强制回滚。


受控异常就是checked Exception ,这些异常在你写代码时候必须用try{}catch语句抓住,或者throw抛出,不然代码编译时候就通不过。比如IOException ,SqlException,FileNotFoundExcption等等,
而运行时异常是你写代码的时候不需要catch,或者throw就可以通过编译的异常,一般由于程序员的错误引起的,比如NullPointException异常,数组越界异常,这些都是没法在 try catch中恢复的,异常需要程序员细心检查出错误。
而error是继承throwable接口,但和异常是不同的概念,error基本上就是jvm运行时内存耗尽,系统崩溃等等重大的错误,级别高于Exception,而且没法恢复。



另见:
http://www.ibm.com/developerworks/cn/java/j-ts1.html
http://www.javaworld.com.tw/confluence/display/opensrc/Spring
http://www.redsaga.com/spring_ref/2.0/html/transaction.html#transaction-declarative


分享到:
评论
1 楼 HappyVeryGood 2013-07-27  
“运行时异常(即非受控异常)自动强制执行整个逻辑工作单元的回滚,但受控异常不会。”

这里的受控异常和非受控异常,不明白是什么意思?楼主可以解释下不。。
我看上面的例子,是这样理解的不过感觉我理解的不对:
异常被捕获了,就是受控异常。否则就是非受控异常。。
但是很显然,上例捕获后有直接抛出去了,我感觉就跟没捕获一样的效果。。不解呀,望楼主解答,,,

相关推荐

    Spring @Transactional工作原理详解

    主要介绍了Spring @Transactional工作原理详解,具有一定借鉴价值,需要的朋友可以参考下。

    Spring声明式事务@Transactional知识点分享

    在本篇文章里小编给大家整理了关于Spring声明式事务@Transactional详解内容,需要的朋友们可以参考下。

    Spring-Reference_zh_CN(Spring中文参考手册)

    9.5.1. 理解Spring的声明式事务管理实现 9.5.2. 第一个例子 9.5.3. 回滚 9.5.4. 为不同的bean配置不同的事务语义 9.5.5. &lt;tx:advice/&gt; 有关的设置 9.5.6. 使用 @Transactional 9.5.6.1. @Transactional 有关的设置 ...

    Spring中@Transactional用法详细介绍

    主要介绍了Spring中@Transactional用法详细介绍的相关资料,需要的朋友可以参考下

    spring boot 全面的样例代码

    - chapter9-2-2:[Spring Boot与Dubbo中管理服务依赖] ### Spring Cloud构建微服务架构 由于Spring Cloud偏宏观架构,Spring Boot偏微观细节,内容上越来越多,为了两部分内容不互相干扰,所以迁移Spring Cloud...

    Spring 2.0 开发参考手册

    9.5.1. 理解Spring的声明式事务管理实现 9.5.2. 第一个例子 9.5.3. 回滚 9.5.4. 为不同的bean配置不同的事务语义 9.5.5. &lt;tx:advice/&gt; 有关的设置 9.5.6. 使用 @Transactional 9.5.7. 插入事务操作 9.5.8. ...

    Spring中文帮助文档

    9.5.1. 理解Spring的声明式事务管理实现 9.5.2. 第一个例子 9.5.3. 回滚 9.5.4. 为不同的bean配置不同的事务语义 9.5.5. &lt;tx:advice/&gt; 有关的设置 9.5.6. 使用 @Transactional 9.5.7. 事务传播 9.5.8. 通知...

    spring chm文档

    9.5.1. 理解Spring的声明式事务管理实现 9.5.2. 第一个例子 9.5.3. 回滚 9.5.4. 为不同的bean配置不同的事务语义 9.5.5. &lt;tx:advice/&gt; 有关的设置 9.5.6. 使用 @Transactional 9.5.7. 插入事务操作 9.5.8. ...

    Spring.3.x企业应用开发实战(完整版).part2

    10.5.2 Hibernate+Spring JDBC混合框架的事务管理 10.6 特殊方法成漏网之鱼 10.6.1 哪些方法不能实施Spring AOP事务 10.6.2 事务增强遗漏实例 10.7 数据连接泄漏 10.7.1 底层连接资源的访问问题 10.7.2 Spring JDBC...

    Spring API

    9.5.1. 理解Spring的声明式事务管理实现 9.5.2. 第一个例子 9.5.3. 回滚 9.5.4. 为不同的bean配置不同的事务语义 9.5.5. &lt;tx:advice/&gt; 有关的设置 9.5.6. 使用 @Transactional 9.5.7. 事务传播 9.5.8. 通知...

    详解Spring Boot 事务的使用

    spring Boot 使用事务非常简单,首先使用注解 @EnableTransactionManagement 开启事务支持后,然后在访问数据库的Service方法上添加注解 @Transactional 便可。接下来通过本文重点给大家介绍spring boot事务的使用,...

    Spring3.x企业应用开发实战(完整版) part1

    10.5.2 Hibernate+Spring JDBC混合框架的事务管理 10.6 特殊方法成漏网之鱼 10.6.1 哪些方法不能实施Spring AOP事务 10.6.2 事务增强遗漏实例 10.7 数据连接泄漏 10.7.1 底层连接资源的访问问题 10.7.2 Spring JDBC...

Global site tag (gtag.js) - Google Analytics