Spring @Transactional

Spring 中使用

  1. 使用注解 @EnableTransactionManagement 开启事务

  2. 配置事务管理器

  3. 使用 @Transactional 注解标注某个方法就可以了

@Configuration
@EnableTransactionManagement // 启用声明式事务
public class AppConfig {
  
    @Bean // 数据源
    public DataSource dataSource() {
        HikariDataSource dataSource = new HikariDataSource();
        dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/mydb");
        dataSource.setUsername("root");
        dataSource.setPassword("password");
        dataSource.setMaximumPoolSize(10);
        return dataSource;
    }
    
    @Bean // 事务管理器
    public DataSourceTransactionManager transactionManager(DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource());
    }
}

SpringBoot 中使用

直接使用,不需要任何配置

默认的数据源和事务管理器都配置好了,也启用了声明式事务(@EnableTransactionManagement

@Transactional 可以写在类上(表示所有方法上都加了),也可以单独方法上。如果类和方法上同时存在,方法上的更优先

@Transactional // 加上这个注解就好了
public void transfer(int fromId, int toId, int amount) {
    // 扣钱
    jdbcTemplate.update("UPDATE account SET balance = balance - ? WHERE id = ?", amount, fromId);
    // 加钱
    jdbcTemplate.update("UPDATE account SET balance = balance + ? WHERE id = ?", amount, toId);
}

配置属性

  • isolation - 事务隔离级别
  • propagation - 事务传播行为
  • timeout - 事务超时时间(秒)
  • readOnly - 是否只读事务(默认为false)
  • rollbackFor/rollbackForClassName - 指定哪些异常触发回滚
  • noRollbackFor/noRollbackForClassName - 指定哪些异常不触发回滚

隔离级别

  • DEFAULT: 使用数据库默认隔离级别
  • READ_UNCOMMITTED: 读未提交
  • READ_COMMITTED: 读已提交(如果要保证不发生脏读,用这个级别,Oracle、PG 默认)
  • REPEATABLE_READ: 可重复读(如果要保证不发生不可重复读,用这个级别,Mysql 默认)
  • SERIALIZABLE: 串行化(如果要保证不发生幻读,用这个级别)

传播行为

  • REQUIRED (默认): 如果当前存在事务,则加入该事务;如果不存在,则创建一个新事务(一个事务)
  • REQUIRES_NEW: 创建一个新事务,如果当前存在事务,则挂起当前事务(两个事务)
  • SUPPORTS: 如果当前存在事务,则加入该事务;如果不存在,则以非事务方式执行(最多一个事务)
  • NOT_SUPPORTED: 以非事务方式执行,如果当前存在事务,则挂起当前事务(可能没有事务)
  • MANDATORY: 必须在一个已有的事务中执行,否则抛出异常
  • NEVER: 必须不在事务中执行,否则抛出异常
  • NESTED: 如果当前存在事务,则在嵌套事务中执行(和加入事务、新开事务都不一样,这里是子事务)
posted @ 2024-11-02 20:40  CyrusHuang  阅读(28)  评论(0)    收藏  举报