Spring-事务管理

文章介绍了事务管理的基本概念,如事务的ACID特性,然后通过一个转账案例展示了在MySQL中如何进行操作。在案例中,由于缺少事务管理,导致数据不一致。接着,文章详细讲解了如何在Spring中配置和使用@Transaction事务注解,包括回滚规则和事务传播行为,确保在异常发生时能保持数据一致性。
摘要由CSDN通过智能技术生成

事务管理

1 事务回顾

mysql多表查询-事务

事务是一组操作的集合,它是一个不可分割的工作单位,这些操作 要么同时成功,要么同时失败。
开启事务(一组操作开始前,开启事务):start transaction / begin ;
提交事务(这组操作全部成功后,提交事务):commit ;
回滚事务(中间任何一个操作出现异常,回滚事务):rollback ;

2 转账案例

2.1 添加账户表

-- 创建账户表,并且添加两条测试数据
create table account (
                         id int primary key auto_increment,
                         name varchar(32),
                         balance float
);
insert into account (name, balance) VALUES ('A', 1000), ('B', 1000);

2.2 导入工程

导入maven工程

2.3 添加持久层代码

public interface AccountMapper {
    //账户加钱
    @Update("update account set balance = balance + #{money} where name = #{name}")
    void add(@Param("name") String name,@Param("money") float money);
    //账户减钱
    @Update("update account set balance = balance - #{money} where name = #{name}")
    void diff(@Param("name") String name,@Param("money") float money);
}

2.4 添加业务层代码

public interface AccountService {

    //转账
    //out 转出账户名
    //in  转入账户名
    //money 金额
    void transfer(String out,String in,Float money);
}

@Service
public class AccountServiceImpl implements AccountService {

    @Autowired
    private AccountMapper accountMapper;

    @Override
    public void transfer(String out, String in, Float money) {
        //1.转出
        accountMapper.diff(out,money);
        //模拟报错
        int i = 1/0;
        //2.转入
        accountMapper.add(in,money);
    }
}

2.5 测试

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfig.class)
public class AccountServiceTest {

    @Autowired
    private AccountService accountService;

    @Test
    public void testTransFer(){
        accountService.transfer("A","B",10F);
    }
}

测试结果:java.lang.ArithmeticException: / by zero(除0错误)
数据库A的金额被修改,但是B没有被修改
A: 990
B:1000

2.6 问题

即使程序运行抛出了异常,转出账户的钱扣除了,但是转入账户的钱没加上,造成了数据的不一致。

3 事务管理

注解:@Transactional
位置:业务(service)层的方法上、类上、接口上
作用:将当前方法交给spring进行事务管理,方法执行前,开启事务;成功执行完毕,提交事务;出现异常,回滚事务

3.1 配置事务管理器

//配置类
@ComponentScan("com.itheima")
@EnableTransactionManagement//开启声明式事务管理
public class SpringConfig {

    //向Spring容器放入事务管理器
    //这个对象的id必须是transactionManager
    @Bean
    public DataSourceTransactionManager transactionManager(DruidDataSource dataSource){
        DataSourceTransactionManager manager = new DataSourceTransactionManager();
        manager.setDataSource(dataSource);
        return manager;
    }

3.2 添加事务注解

在转账方法上添加@Transactional注解,注意方法中要模拟异常
@Transactional //事务处理注解(可以标注在方法上,类上,接口上)

    @Override
    @Transactional //事务处理注解(可以标注在方法上,类上,接口上)
    public void transfer(String out, String in, Float money) {
        //1.转出
        accountMapper.diff(out,money);
        //模拟报错
        int i = 1/0;
        //2.转入
        accountMapper.add(in,money);
    }

3.3 测试

```java
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfig.class)
public class AccountServiceTest {

    @Autowired
    private AccountService accountService;

    @Test
    public void testTransFer(){
        accountService.transfer("A","B",10F);
    }
}

测试结果:java.lang.ArithmeticException: / by zero(除0错误)
因为出现报错.事务回滚,数据库没有被修改

4 事务属性

4.1 rollbackFor(回滚)

默认情况下,只有出现 RuntimeException 才回滚异常,rollbackFor属性用于控制让非运行时异常也回滚。

   @Override
    //事务处理注解(可以标注在方法上,类上,接口上)
    @Transactional(rollbackFor = Exception.class) //默认是在RuntimeException才回滚
    public void transfer(String out, String in, Float money) throws Exception {
        //1.转出
        accountMapper.diff(out,money);
        //模拟报错
        if(true){
            throw new Exception("出错啦");
        }
        //2.转入
        accountMapper.add(in,money);
    }

测试结果:
出现Exception错误,事务回滚

4.2 propagation(传播)

propagation称为事务传播行为,表示当一个事务方法被另一个事务方法调用时,应该如何进行事务控制

    @Transactional
    public void a(){
        b();
    }

    @Transactional(propagation = Propagation.REQUIRED)//【默认值】需要事务,有则加入,无则创建新事务
    public void b(){

    }

Spring支持通过配置的形式来实现7种事务传播行为,我们需要掌握其中的前两种

属性值含义
REQUIRED【默认值】需要事务,有则加入,无则创建新事务
REQUIRES_NEW需要新事务,无论有无,总是创建新事务
SUPPORTS支持事务,有则加入,无则在无事务状态中运行
NOT_SUPPORTED不支持事务,在无事务状态下运行,如果当前存在已有事务,则挂起当前事务
MANDATORY必须有事务,否则抛异常
NEVER必须没事务,否则抛异常
NESTED如果一个活动的事务存在,则运行在一个嵌套的事务中。
如果没有活动事务, 则开启一个新的事务。内层事务依赖于外层事务。
外层事务失败时,会回滚内层事务所做的动作。而内层事务操作失败并不会引起外层事务的回滚
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值