Spring-事务管理

Spring 事务管理由两种方式:

  • 一种是传统的编程式事务管理,通过编写代码实现事务管理,包括定义事务的开始、程序正常执行后的事务提交、异常时进行的事务回滚。
  • 另一种是基于 AOP 技术实现的声明式事务,其主要思想是将事务管理作为一个 “方面” 代码单独编写,程序员只关心核心业务逻辑代码,然后通过 AOP 技术将事务管理的 “方面” 代码织入到业务类中。声明式事务的缺点在于,只能作用于方法级别,无法做到像编程式事务那样能控制到代码块级别

Spring 声明式事务管理既可以通过 AOP 配置方式实现,也可以通过 @Transactional 注解的方式来实现。Spring3 的事务规则也就是事务传播行为,常见的事务传播行为如下:

名称 说明
REQUIRED 表示当前方法必须运行在一个事务环境中,如果有一个现有事务正在运行中,该方法将运行在这个事务中,否则,就要开始一个新的事务
REQURIESNEW 表示当前方法必须运行在自己的事务里
SUPPORTS 表示当前方法不需要事务处理环境,但如果有一个事务正在运行的话,则这个方法也可以运行在这个事务中
MANDATORY 表示当前方法必须运行在一个事务上下文中,否则就抛出异常
NEVER 表示当前方法不应该运行在一个事务上下文中,否则就抛出异常

事务管理的主要任务是事务的创建、事务的回滚和事务的提交,是否需要创建事务以及如何创建事务,是由事务传播行为控制的,通常数据的读取可以不需要事务管理,或者可以指定为只读事务,而对于数据的增加、删除和修改操作,则有必要进行事务管理。如果没有指定事务的传播型行为,Spring3 默认将采用 REQUIRED

基于 AOP 的事务管理

下面开始配置基于 AOP 的事务管理。

所有的配置都是在 Spring 配置文件 applicationContext.xml 中完成:

  • <beans> 标记中添加 AOP 所需的常用命名空间声明:

    1
    2
    3
    4
    5
    6
    <beans
    xmlns:aop="http://www.springframework.org/schema/aop"
    ...
    xsi:schemaLocation="http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
    ...">
  • 声明事务管理器。使用声明式事务,需要提供声明事务管理器。在 Spring 和 Hibernate 的整合中,在 Spring 配置文件中声明一个 Hibernate 事务管理器:

    1
    2
    3
    4
    <!-- 声明 Hibernate 事务管理器 -->
    <bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory" />
    </bean>
  • 定义事务通知,首先指定一个事务管理器,然后在其属性中声明事务规则:

    1
    2
    3
    4
    5
    6
    7
    8
    <!-- 定义事务通知 -->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
    <!-- 指定事务传播规则 -->
    <tx:attributes>
    <!-- 对所有方法应用 REQUIRED 事务规则 -->
    <tx:method name="*" propagation="REQUIRED"></tx:method>
    </tx:attributes>
    </tx:advice>

在定义事务传播规则时,对所有方法应用 REQUIRED 事务规则,表示当前方法必须运行在一个事务环境中,如果一个现有事务正在运行中,该方法将运行在这个事务中,否则,就开始一个新的事务。

  • 定义一个切面,并将事务通知与切面组合,即定义哪些方法应用这些规则:
    1
    2
    3
    4
    5
    6
    <aop:config>
    <!-- 对 com.ssh2.biz 包下的所有类的所有方法都应用事务规则 -->
    <aop:pointcut id="bizMethods" expression="execution(* com.ssh2.biz.*.*(..))" />
    <!-- 将事务通知与切面组合 -->
    <aop:advice advice-ref="txAdvice" pointcut-ref="bizMethods" />
    </aop:config>

到此,基于 AOP 的声明式事务配置完成了。

基于 @Transactional 注解的事务管理

参数名 说明
propagation 设置事务的传播规则,格式如:@Transactional(propagation=Propagation.REQUIRED)
rollbackFor 需要回滚的异常类,当方法中抛出异常时,则进行事务回滚。单一异常类格式:@Transactional(rollbackFor=RuntimeException.class) 多个异常类格式:@Transactional(rollbackFor={RuntimeException.class,Exception.class})
rollbackForClassName 需要回滚的异常类名,当方法抛出指定异常类名称时,则进行回滚。单一异常类名称格式:@Transactional(rollbackForClassName=”RuntimeException”) 多个异常类名称格式:@Transactional(rollbackForClassName={“RuntimeException”,”Exception”})
isolation 事务隔离级别,用于处理多个事务并发,基本不需要设置
timeout 设置事务的超时秒数
readOnly 事务是否只读,设置为 true 表示只读