问题描述:
假如A有500,B有500,A向B转账
(1)当执行正确的转账操作时A为400,B为600
(2)当执行转账操作时遇到错误,SQL语句正常执行A为400,B为500,此时损失了100。此时就需要添加事务。它的作用是当你的方法正确运行时就提交事务并更新数据库,当方法中出现错误时回滚事务并且不会更新数据库。
(1)的情况
(2)的情况
此时支出的SQL语句会执行,也就是说可以admin的金额会减少100,而张三的金额却因为遇到了错误信息而不会执行,这时admin为300,张三为600
出现这样的情况,就需要用事务。
通过 jdbc 持久化事务,对于事务配置实现由两种方式即:Xml 配置,注解配置。
一、Xml 配置
1、在spring.xml配置文件的添加事务和aop的命名空间
<!--事务-->
xmlns:tx="http://www.springframework.org/schema/tx"
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
<!--Aop-->
xmlns:aop="http://www.springframework.org/schema/aop"
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
2、设置aop代理
<!-- 开启AOP代理 -->
<aop:aspectj-autoproxy />
3、配置事务管理器
<!-- 事务管理器定义 -->
<bean id="txManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--数据源 -->
<property name="dataSource" ref="dataSource"></property>
</bean>
4、配置事务相关通知
<!-- 配置事务通知 transaction-manager属性表示这个事务通知是哪个事务管理器管理的-->
<tx:advice id="txAdvice" transaction-manager="txManager">
<!--对以add update delete query开头的所有方法进行事务处理-->
<tx:attributes>
<!--定义什么方法需要使用事务 name代表的是方法名(或方法匹配)-->
<!-- 匹配以 add 开头的所有方法均加入事务 -->
<tx:method name="insert*" propagation="REQUIRED" />
<!-- 匹配以 update 开头的所有方法均加入事务 -->
<tx:method name="update*" propagation="REQUIRED" />
<!-- 匹配以 delete 开头的所有方法均加入事务 -->
<tx:method name="delete*" propagation="REQUIRED" />
<!-- 匹配以 query 开头的所有方法均加入事务 -->
<tx:method name="query*" read-only="true" />
</tx:attributes>
</tx:advice>
5、配置aop
<!-- aop 切面定义 (切入点和通知) -->
<aop:config>
<!-- 设置切入点 设置需要被拦截的方法 -->
<aop:pointcut expression="execution(* com.xxxx.service..*.*(..) )" id="cut"
/>
<!-- 设置通知 事务通知 -->
<aop:advisor advice-ref="txAdvice" pointcut-ref="cut"/>
<aop:adviso
此时第一个方法已经完成,我们来试验一下(admin和张三均为500),不过此时要将方法名改成updade开头的,例如updateMoney,实验结果就是方法中遇见错误信息,数据库不进行更新
这是通过改方法名,但如果我们就要让transMoney当方法名呢?这时可以在spring.xml的事务相关通知里添加一行
<tx:method name="transMoney*" propagation="REQUIRED" />
两者效果一样。但是比较麻烦,如果有很多方法就要一个个的去手动添加,这时来看第二个方法吧。
二、注解配置
1、在spring.xml中添加
<!-- 开启注解事务支持-->
<tx:annotation-driven transaction-manager="txManager"/>
2、在Service 方法上在需要添加事务的方法上加入事务注解
@Transactional(propagation = Propagation.REQUIRED)
实验一下:
可以看到,这种方法也成功添加了事务,而且相比第一种方法更为简单。
总结:
添加事务的方法:(1)通过xml配置
(2)通过注解配置