5. Spring的事务管理
5.1 事务管理概述
在负责事务管理的jar包中,找到trancation包,其中包括事务管理的三个核心接口:PlatformTransactionManager、TransactionDefinition 和 TransactionStatus。
5.1.1事务管理的核心接口
1.PlatformTrancationManager
这个接口是Spring提供的平台事务管理器,主要用于管理事务,包含三个用于事务操作的方法。
- TransactionStatus getTransaction(TransactionDefinition
definition):用于获取事务状态信息。 - void commit(TransactionStatus status):用于提交事务。
- void rollback(TransactionStatus status):用于回滚事务。
2.TransactionDefinition
TransactionDefinition 接口是事务定义(描述)的对象,它提供了事务相关信息获取的方法,其中包括五个操作,具体如下。
- String getName():获取事务对象名称。
- int getIsolationLevel():获取事务的隔离级别。
- intgetPropagationBehavior():获取事务的传播行为。
- int getTimeout():获取事务的超时时间。
- boolean isReadOnly():获取事务是否只读。
传播行为的种类如下表所示:
属性名称 | 值 | 描述 |
---|---|---|
PROPAGATION_REQUIRED | required | 支持当前事务。如果 A 方法已经在事务中,则 B 事务将直接使用。否则将创建新事务 |
PROPAGATION_SUPPORTS | supports | 支持当前事务。如果 A 方法已经在事务中,则 B 事务将直接使用。否则将以非事务状态执行 |
PROPAGATION_MANDATORY | mandatory | 支持当前事务。如果 A 方法没有事务,则抛出异常 |
PROPAGATION_REQUIRES_NEW | requires_new | 将创建新的事务,如果 A 方法已经在事务中,则将 A 事务挂起 |
PROPAGATION_NOT_SUPPORTED | not_supported | 不支持当前事务,如果 A 方法在事务中,则抛出异常 |
PROPAGATION_NEVER | never | 不支持当前事务,总是以非事务状态执行。如果 A 方法已经在事务中,则将其挂起 |
PROPAGATION.NESTED | nested | 嵌套事务,底层将使用 Savepoint 形成嵌套事务 |
3.TransactionStatus
TransactionStatus 接口是事务的状态,它描述了某一时间点上事务的状态信息。
- void flush() 刷新事务
- boolean hasSavepoint() 获取是否存在保存点
- boolean isCompleted() 获取事务是否完成
- boolean isNewTransaction() 获取是否是新事务
- boolean isRollbackOnly() 获取是否回滚
- void setRollbackOnly() 设置事务回滚
5.1.2事务管理的方式
Spring 事务管理分为两种方式,一种是传统的编程式事务管理,另一种是声明式事务管理。
编程式事务管理:要包括定义事务的开始,正常执行后的事务提交,异常时事务的回滚
声明式事务管理:通过AOP技术实现事务管理
5.2 声明式事务管理
5.2.1 基于xml方式的声明式事务管理
这种方式通过在事务文件中配置事务规则的相关声明来实现,利用tx命名空间来配置事务。该属性配置的结构如下
首先在上次用来声明方法的接口中,声明方法,并在实现类中实现
public void transfer(String outUser, String inUser, Double money) {
// TODO Auto-generated method stub
this.jdbcTemplate.update("update account set balance = balance + ? "
+"where username = ? ",money,inUser);
// int i = 1 /0;
this.jdbcTemplate.update("update account set balance = balance - ? "
+"where username = ? ",money,outUser);
}
编写xml文档
<!-- 4.事务管理器,依赖于数据源 -->
<bean id="transactionManager" class=
"org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- 5.编写通知:对事务进行增强(通知),需要编写对切入点和具体执行事务细节 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!-- name:*表示任意方法名称 -->
<tx:method name="*" propagation="REQUIRED"
isolation="DEFAULT" read-only="false" />
</tx:attributes>
</tx:advice>
<!-- 6.编写aop,让spring自动对目标生成代理,需要使用AspectJ的表达式 -->
<aop:config>
<!-- 切入点 -->
<aop:pointcut expression="execution(* com.itheima.jdbc.*.*(..))"
id="txPointCut" />
<!-- 切面:将切入点与通知整合 -->
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut" />
</aop:config>
编写测试类,测试运行
@Test
public void transtest(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
AccountDao accountDao = (AccountDao)applicationContext.getBean("accountDao");
accountDao.transfer("张伟隆", "123", 50.0);
System.out.print("成功");
}
运行结果如下
注意这里需要导入新的jar包,起初没注意到这点,在这里改了半天
5.2.2 基于Annotation方式的声明式事务管理
这种方式比较简易,仅仅需要在xml文档中,注册事务注解驱动
将原先xml文档中
<!-- 5.编写通知:对事务进行增强(通知),需要编写对切入点和具体执行事务细节 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!-- name:*表示任意方法名称 -->
<tx:method name="*" propagation="REQUIRED"
isolation="DEFAULT" read-only="false" />
</tx:attributes>
</tx:advice>
<!-- 6.编写aop,让spring自动对目标生成代理,需要使用AspectJ的表达式 -->
<aop:config>
<!-- 切入点 -->
<aop:pointcut expression="execution(* com.itheima.jdbc.*.*(..))"
id="txPointCut" />
<!-- 切面:将切入点与通知整合 -->
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut" />
</aop:config>
替换为
<tx:annotation-driven transaction-manager="transactionManager"/>
现在需要在测试方法的上面添加注解
@Transactional(propagation = Propagation.REQUIRED,
isolation = Isolation.DEFAULT,readOnly = false)
关于 @Transactional 的参数,有如下
readOnly
该属性用于设置当前事务是否为只读事务,设置为true表示只读,false则表示可读写,默认值为false。例如:@Transactional(readOnly=true)
rollbackFor
该属性用于设置需要进行回滚的异常类数组,当方法中抛出指定异常数组中的异常时,则进行事务回滚。例如:
指定单一异常类:@Transactional(rollbackFor=RuntimeException.class)
指定多个异常类:@Transactional(rollbackFor={RuntimeException.class, Exception.class})
rollbackForClassName
该属性用于设置需要进行回滚的异常类名称数组,当方法中抛出指定异常名称数组中的异常时,则进行事务回滚。例如:
指定单一异常类名称:@Transactional(rollbackForClassName="RuntimeException")
指定多个异常类名称:@Transactional(rollbackForClassName={"RuntimeException","Exception"})
noRollbackFor
该属性用于设置不需要进行回滚的异常类数组,当方法中抛出指定异常数组中的异常时,不进行事务回滚。例如:
指定单一异常类:@Transactional(noRollbackFor=RuntimeException.class)
指定多个异常类:@Transactional(noRollbackFor={RuntimeException.class, Exception.class})
noRollbackForClassName
该属性用于设置不需要进行回滚的异常类名称数组,当方法中抛出指定异常名称数组中的异常时,不进行事务回滚。例如:
指定单一异常类名称:@Transactional(noRollbackForClassName="RuntimeException")
指定多个异常类名称:
@Transactional(noRollbackForClassName={"RuntimeException","Exception"})
propagation
该属性用于设置事务的传播行为,具体取值可参考表6-7。
例如:@Transactional(propagation=Propagation.NOT_SUPPORTED,readOnly=true)
isolation
该属性用于设置底层数据库的事务隔离级别,事务隔离级别用于处理多事务并发的情况,通常使用数据库的默认隔离级别即可,基本不需要进行设置
timeout
该属性用于设置事务的超时秒数,默认值为-1表示永不超时
测试运行成功