Spring 事务操作

概述

什么是事务?

事务是数据库操作的最基本单元,把一系列操作视为一个整体的功能被称为事务,作为事务时这一系列操作要全部成功才被视为成功,否则只要由一个操作失败就被视为失败。

单条SQL语句就是一个事务,这种事务被成为隐式事务。

事务特性ACID

  • Atomic 原子性:原子是不可分割的,事务要么全部执行,要么不执行
  • Consistency 一致性:事务提交前后的状态是一致的,比如银行转账,转账前后各人的账户余额可能变了,但钱的总额不变
  • Isolation 隔离性:多个事务并发执行时,不被其他事务干扰
  • Duration 持久性:事务完成后,修改被持久化存储

事务参数

  • @Transanctional
  • @EnableTransactionManagement

Transanctional参数配置

image-20210908235811790

propagation事务传播行为

事务传播行为:事务方法之间发生调用时,事务该如何进行传播

在这里插入图片描述

传播属性描述
REQUIRED默认值,如果有事务在运行就在当前事务运行,没有事务时创建新事务,这是最常用的传播行为,已经满足绝大部分需求
REQUIRES_NEW当前方法必须启动新事务
SUPPORTS如果有事务在运行,就运行在事务中,可以不在事务中运行,这种传播级别可用于select方法,因为select可以在事务中执行,也可以不需求事务
NOT_SUPPORTED不能运行在事务中,如果有运行的事务,就将它挂起
MANDATORY必须运行在事务中,如果没有正在运行的事务就抛出异常 ,这种传播级别可用于核心更新逻辑,比如用户余额变更
NEVER必须不运行在事务中,如果有正在运行的事务就抛出异常
NESTED如果有事务在运行,就在事务中嵌套事务运行,没有事务就创建事务
@Service
@Transactional(propagation = Propagation.REQUIRED)
public class AccountService {
    
}

isolation事务隔离级别

两个并发执行的事务,如果涉及到操作同一条记录时,可能会带来数据的不一致性,比如脏读,不可重复度,幻读等。隔离级别可以让我们有选择性的避免数据不一致的问题。

在这里插入图片描述

  • Read Uncommited 事务可以看到其他事务未提交的数据
  • Read Commited 一个事务修改过的数据提交后才能被其他事务看到
  • Repeatable Read 在Read Commited的基础上,保证了不可重复读
  • Serializable 代价最高最可靠的隔离级别,事务被处理为串行执行,执行效率太低
Isolation Level脏读不可重复读幻读
Read UncommitedYesYesYes
Read Commited-YesYes
Repeatable Read--Yes
Serializable---

脏读:一个事务读到另一个事务更新后但未提交的数据,如果另一个事务回滚,当前事务读到的就是脏数据

时刻事务A事务B
1SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
2BEGIN;BEGIN;
3UPDATE students SET name = ‘Bob’ WHERE id = 1;
4SELECT * FROM students WHERE id = 1;
5ROLLBACK;
6SELECT * FROM students WHERE id = 1;
7COMMIT;

不可重复读:一个事务第二次读取同一数据时刚好读取到了另一个事务更新提交的数据,两次读取的数据不一致

时刻事务A事务B
1SET TRANSACTION ISOLATION LEVEL READ COMMITTED;SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
2BEGIN;BEGIN;
3SELECT * FROM students WHERE id = 1;
4UPDATE students SET name = ‘Bob’ WHERE id = 1;
5COMMIT;
6SELECT * FROM students WHERE id = 1;
7COMMIT;

幻读:一个事务查询不到该条记录,而因为在另一个事务更新提交事务后生成了该条记录,虽然这时当前事务还是查询不到该条记录但竟然发现能对该条记录进行更新,像做梦一样

时刻事务A事务B
1SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
2BEGIN;BEGIN;
3SELECT * FROM students WHERE id = 99;
4INSERT INTO students (id, name) VALUES (99, ‘Bob’);
5COMMIT;
6SELECT * FROM students WHERE id = 99;
7UPDATE students SET name = ‘Alice’ WHERE id = 99;
8SELECT * FROM students WHERE id = 99;
9COMMIT;
@Service
@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.REPEATABLE_READ)
public class AccountService {
}

timeout超时时间

设置超时时间,超时则回滚,单位为秒

readOnly只读

默认值为false,可以更新表,可以查询, 设为true只能查询

rollbackFor

设置出现哪些异常回滚

noRollbackFor

设置出现哪些异常不回滚

配置事务

配置类

  • @EnableTransactionManagement
  • 注入dataSource
  • 注入TransactionManager
@Configuration
@ComponentScan("com.npc")
@PropertySource("jdbc.properties")
@EnableTransactionManagement
public class SpringConfig {
	
	@Value("${jdbc.driverclass}")
	String jdbcDriver

	@Value("${jdbc.url}")
    String jdbcUrl;

    @Value("${jdbc.username}")
    String jdbcUsername;

    @Value("${jdbc.password}")
    String jdbcPassword;
    
    @Bean
    public DruidDataSource getDruidDataSource() throws IOException {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName(jdbcDriver);
        dataSource.setUrl(jdbcUrl);
        dataSource.setUsername(jdbcUsername);
        dataSource.setPassword(jdbcPassword);
        return dataSource;
    }

    @Bean
    public JdbcTemplate getJdbcTemplate(@Autowired DataSource dataSource) {
        JdbcTemplate jdbcTemplate = new JdbcTemplate();
        jdbcTemplate.setDataSource(dataSource);
        return jdbcTemplate;
    }

    @Bean
    public DataSourceTransactionManager getDataSourceTransactionManager(@Autowired DataSource dataSource) {
        DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
        transactionManager.setDataSource(dataSource);
        return transactionManager;
    }
}

配置切入点

  • @Transactional
@Service
@Transactional
public class AccountService {
    public void transfer(int from, int to, int money) {
        accountDao.reduceMoneny(from, money);
        // 触发异常,查看事务作用
        // int i = 10/0;
        accountDao.addMoney(to, money);
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Lor :)

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值