Spring事务管理

一、事务的概念

事务(Transaction)是指逻辑上的一组操作,这组操作要么全部成功,要么全部失败。
事务拥有四个特性:

  1. 原子性: 一组事务不可分割,要么全部发生,要么都不发生
  2. 一致性: 一组事务发生前后的数据量应保持一致
  3. 隔离性: 多个并发事务之间应相互隔离、互不干扰
  4. 持久性: 一组事务一旦执行成功,它带来的改变是永久性的

二、安全问题

如果隔离处理不当,可能导致以下三种读写问题发生:

  1. 脏读: A事务读取了B事务改写但还未提交的数据(如果B事务被回滚,那么这个数据是无效的)
  2. 不可重复读: 在同一事务中多次读取同一数据,获得的结果不同(在查询期间该数据被其它事务修改了)
  3. 幻读: 在同一事务中多次读取数据量,获得的数目不相等(在查询期间另一个事务插入了一些记录)

三、隔离级别

级别名称原理效果
READ_UNCOMMITED无限制
READ_COMMITED允许在并发事务提交后读取可防止脏读
REPEATABLE_READ对相同字段的多次读取均一致,除非被事务本身改变可防止脏读、不可重复读
SERIALIZABLE依据ACID原则完全锁定事务中的数据,但速度最慢可防止脏读、不可重复读、幻读
DEFAULT使用数据库默认的级别MySQL默认为REPEATABLE_READ

四、传播行为

行为名称说明
PROPAGATION_REQUIRED支持当前事务,如果不存在就创建一个
PROPAGATION_REQUIRES_NEW如果有事务存在,挂起当前事务,创建一个新事务
PROPAGATION_NESTED如果当前事务存在,则嵌套事务执行

五、编程式事务管理

暂时省略,可参考其它博客


六、声明式事务管理

【模拟情景】假设现有a、b两个账户,它们各拥有1000元的资金,某时刻a账户向b账户转账300元,在转账的过程中突发断电。
初始数据库信息如下:
在这里插入图片描述
实现DAO层:

public class AccountDao extends JdbcDaoSupport {

    /**
     * 资金转出的方法
     * @param out 发起方
     * @param money 金额
     */
    public void outMoney(String out, Double money) {
        String sql = "update account set money = money - ? where name = ?";
        this.getJdbcTemplate().update(sql, money, out);
    }

	/**
     * 资金转入的方法
     * @param in 接收方
     * @param money 金额
     */
    public void inMoney(String in, Double money) {
        String sql = "update account set money = money + ? where name = ?";
        this.getJdbcTemplate().update(sql, money, in);
    }
    
}

实现Service层:

public class AccountService {

    private AccountDao accountDao;

    public void setAccountDao(AccountDao accountDao) {
        this.accountDao = accountDao;
    }

    /**
     * 转账的方法
     * @param out 转出账号
     * @param in 转入账号
     * @param money 金额
     */
    public void transfer(String out, String in, Double money) {
        accountDao.outMoney(out, money);
        int i = 1 / 0; // 制造异常来模拟断电情景
        accountDao.inMoney(in, money);
    }

}

完成相关的Spring配置后,执行accountService.transfer("a", "b", 300d);
如果没有进行事务管理,那么账户a将扣除300元,但账户b并不会收到这300元:
在这里插入图片描述

1. 基于TransactionProxyFactoryBean

XML的配置部分如下:

<!-- 配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
	<property name="dataSource" ref="dataSource"/>
</bean>

<!-- 配置业务层的代理 -->
<bean id="accountServiceProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
	<!-- 配置目标对象 -->
	<property name="target" ref="accountService"/>
    <!-- 注入事务管理器 -->
    <property name="transactionManager" ref="transactionManager"/>
    <!-- 注入事务的属性 -->
    <property name="transactionAttributes">
    	<props>
        	<prop key="transfer">PROPAGATION_REQUIRED</prop>
        </props>
   	</property>
</bean>

注意:由于本方式为手动配置代理,此时应用id为accountServiceProxy的代理对象进行转账操作,不能再用原先的accountService对象


2. 基于AspectJ框架

XML的配置部分如下:

<!-- 配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
	<property name="dataSource" ref="dataSource"/>
</bean>
    
<!-- 配置事务的通知 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
	<tx:attributes>
		<tx:method name="transfer" propagation="REQUIRED"/>
   	</tx:attributes>
</tx:advice>

<!-- 配置切面 -->
<aop:config>
	<!-- 配置切入点 -->
	<aop:pointcut id="pointcut1" expression="execution(* AccountService+.*(..))"/>
	<!-- 配置切面 -->
    <aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut1"/>
</aop:config>

3. 基于注解

XML的配置部分如下:

<!-- 配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
	<property name="dataSource" ref="dataSource"/>
</bean>

<!-- 开启事务的注解扫描 -->
<tx:annotation-driven transaction-manager="transactionManager"/>

在需要进行事务管理的类上添加注解:

@Transactional(propagation = Propagation.REQUIRED)
public class AccountService {
...
}

配置了事务管理之后,a扣款和b收款合为了一个不可分割的整体,即使a扣款执行后系统发生了中止,整体也会回滚到初始状态,不会再出现金额丢失的情况:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值