概念
Spring的声明式事务管理是通过AOP技术实现的事务管理,其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行目标方法之后根据执行情况提交或者回滚事务。 声明式事务管理的最大优点是不需要通过编程的方式管理事务,因而不需要在业务逻辑代码中掺杂事务处理代码,只需要相关的事务规则声明便可以将事务规则应用到业务逻辑中,在通常情况下,在开发中使用声明式事务管理不仅因为简单,更主要因为纯业务代码不会被污染,极大地方便代码的后期维护。
业务场景模拟
银行转账问题,用户A要向用户B转账,在后端代码中通常分为两个操作,先将用户A的金额减少,在将用户B的金额增加,正常情况下会执行成功,但是如果在两个操作之间发生了异常,那么将会出现,用户A的金额减少,但是用户B的金额没有增加的情况。
public void changeSal(int id1,int id2,int salary){
UserDao userDao = sqlSessionTemplate.getMapper(UserDao.class);
//增加金额
userDao.inSal(id1,salary);
//发异常
int i = 10/0;
//减少金额
userDao.outSal(id2,salary);
}
在MySql中,任意的一个增加,删除,修改操作其实都是一个隐式的事务开始和提交过程,事务虽然有回滚功能,但是回滚功能只针对当前事务,而不同的增删改操作是不同的事务,所以我们需要将转账业务的两个修改操作变成一个事务,这样才能在事务发生错误时回滚事务的操作,此时就用到了spring中的声明式事务处理方式。
步骤操作
第一步
导入事务管理的相关maven坐标
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
第二步
在spring核心配置文件中配置事务相关的文件头<tx/>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
</beans>
第三步
分为注解和XML方式
注解方式
<!-- 在beans.xml文件中 配置声明式事务管理注解驱动-->
<tx:annotation-driven transaction-manager="transactionManager">
</tx:annotation-driven>
//使用注解@Transactional
@Transactional
public void changeInfo(){
studentDao.updateAgeById(100,1);
System.out.println("-----------");
int i = 1/0;
studentDao.updateNameById("test1",1);
}
XML方式
<!-- 配置 aop -->
<aop:config>
<!-- 配置切入点表达式 -->
<aop:pointcut expression="execution(* com.xszx.service.*.*(..))"
id="pt1"/>
<!-- 建立事务的通知和切入点表达式的关系 -->
<aop:advisor advice-ref="txAdvice" pointcut-ref="pt1"/>
</aop:config>
<!-- 事务的配置 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<!--配置事务的属性 -->
<tx:attributes>
<!-- 指定方法名称:是业务核心方法
read-only:是否是只读事务。默认 false,不只读。
isolation:指定事务的隔离级别。默认值是使用数据库的默认隔离级别。
propagation:指定事务的传播行为。
timeout:指定超时时间。默认值为: -1。永不超时。
rollback-for:用于指定一个异常,当执行产生该异常时,事务回滚。产生其他异常,事务不回滚。
没有默认值,任何异常都回滚。
no-rollback-for:用于指定一个异常,当产生该异常时,事务不回滚,产生其他异常时,事务回
滚。没有默认值,任何异常都回滚。
-->
<tx:method name="addUser" propagation="REQUIRED"/>
<tx:method name="changeSal" propagation="SUPPORTS"/>
</tx:attributes>
</tx:advice>