专注于 JetBrains IDEA 全家桶,永久激活,教程
持续更新 PyCharm,IDEA,WebStorm,PhpStorm,DataGrip,RubyMine,CLion,AppCode 永久激活教程

SpringBoot事务管理详解:从基础到高级实战,全面掌握事务控制!

SpringBoot事务管理详解:从基础到高级实战

一、事务管理基础概念

1.1 什么是事务?

专业解释:事务(Transaction)嘛,就是数据库操作的一个执行单元,它是由一堆SQL语句组成的,反正要么全成功,要么全失败,不能隔开来执行。

通俗理解:你想啊,就像是你从A账户给B账户转100块钱。A账户得扣100,而B账户得加100。要么两者都成功,要么都失败,不能让A账户扣了钱,B账户没收到,懂吧?

1.2 事务的四大特性(ACID)

特性 全称 解释 生活化例子
原子性 Atomicity 事务是不可分割的单位,要么全做,要么全不做 转账是个整体,要么成功,要么失败,不能说A扣钱了,B没收到
一致性 Consistency 事务前后,数据库状态一致 转账前后,A和B的账户总额不会乱,没变
隔离性 Isolation 并发事务互不影响 多人转账给一个人,结果一样对,不管顺序
持久性 Durability 提交的事务就是永久性的,不会丢 转账成功了,系统崩了,钱照样在那,不丢

1.3 Spring事务管理核心接口

Spring事务管理的核心接口就那几个,看好了:

  • PlatformTransactionManager - 就是事务管理器的顶级接口。
  • TransactionDefinition - 定义事务的那些信息:隔离级别、传播行为啥的。
  • TransactionStatus - 事务的运行状态,能看状态,方便控制。

二、SpringBoot事务基础配置

2.1 快速启用事务管理

SpringBoot呢,基本上就一个注解@EnableTransactionManagement就搞定了,当然,SpringBoot的自动配置给咱们提前处理好这些事儿了。

@SpringBootApplication
@EnableTransactionManagement // 其实SpringBoot会自动帮你启用的
public class MyApp {
    public static void main(String[] args) {
        SpringApplication.run(MyApp.class, args); // 启动应用
    }
}

注释:你看,代码就是这么简单,@EnableTransactionManagement注解就是让SpringBoot启用事务管理,虽然SpringBoot自己也会自动配置这部分。

2.2 配置数据源和事务管理器

SpringBoot自动给你配置好一个DataSourceTransactionManager,当然你也可以自定义一个。随便来点儿:

@Configuration
public class DataSourceConfig {

    @Bean
    public DataSource dataSource() {
        // 就拿HikariCP做个例子
        HikariDataSource dataSource = new HikariDataSource();
        dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/mydb"); // 数据库URL
        dataSource.setUsername("root"); // 用户名
        dataSource.setPassword("password"); // 密码
        dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver"); // 驱动类名
        return dataSource; // 返回数据源
    }

    @Bean
    public PlatformTransactionManager transactionManager(DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource); // 创建事务管理器
    }
}

注释:这段代码做了两件事儿,一是配置数据源,二是给事务管理器配了个DataSourceTransactionManager。完全自定义,没问题。

三、声明式事务管理

3.1 @Transactional注解基础使用

@Transactional注解的作用可大了,想搞事务管理,随便标上它,嘿,事务就来了。来看看我写的这个示例:

@Service
public class OrderService {

    @Autowired
    private OrderDao orderDao;

    @Autowired
    private AccountDao accountDao;

    @Transactional
    public void createOrder(Order order) {
        // 1. 创建订单
        orderDao.insert(order);

        // 2. 扣减账户余额
        accountDao.deduct(order.getUserId(), order.getAmount());

        // 如果这块儿抛个异常,前面两个操作都得回滚
    }
}

注释:这个方法中,@Transactional的标注就是告诉Spring:这个方法得管理事务。要是中间报错,前面的数据库操作都得回滚掉。

3.2 @Transactional注解属性详解

属性 类型 说明 默认值
propagation Propagation 事务传播行为 REQUIRED
isolation Isolation 事务隔离级别 DEFAULT(数据库默认)
timeout int 事务超时设置(秒) -1(系统默认)
readOnly boolean 是否只读事务 false
rollbackFor Class[] 哪些异常触发回滚 {}
rollbackForClassName String[] 异常类名触发回滚 {}
noRollbackFor Class[] 哪些异常不触发回滚 {}
noRollbackForClassName String[] 异常类名不回滚 {}

注释:有时候,你得调整这些属性,决定事务是咋传播、咋隔离的。Spring已经给你预设了很多默认的值,你可以根据需要改变。

3.3 事务传播行为详解

这是重点,事务传播行为控制了事务调用时怎么走。

传播行为 解释 生活化例子
REQUIRED 如果没有事务就创建,若有事务就加入 就像朋友聚餐,有人组织就加入,没组织自己来
SUPPORTS 支持事务,若没有就不创建 同上,有人组织就一起,没组织自己搞
MANDATORY 必须有事务,没有就报错 聚餐必须有人组织,没有就别吃
REQUIRES_NEW 强行新建事务 无论如何,自己单独搞一个
NOT_SUPPORTED 取消事务,若有就挂起 自己单干,完全不管大伙
NEVER 不参与事务,若有事务就报错 绝对不参与,不想管
NESTED 嵌套事务,内外独立 大聚餐中的小聚餐,单独回滚

注释:这里的REQUIRES_NEW就像你自己组织一个聚会,完全不管别人咋办。

@Service
public class OrderService {

    @Autowired
    private InventoryService inventoryService;

    @Transactional(propagation = Propagation.REQUIRED)
    public void placeOrder(Order order) {
        saveOrder(order); // 主业务

        try {
            // 调用库存服务,使用REQUIRES_NEW传播行为
            inventoryService.updateStock(order.getProductId(), order.getQuantity());
        } catch (Exception e) {
            log.error("库存更新失败", e); // 库存更新失败也不影响主订单创建
        }
    }
}

@Service
public class InventoryService {

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void updateStock(Long productId, int quantity) {
        // 更新库存逻辑
    }
}

注释:在InventoryService中,updateStock方法标注了REQUIRES_NEW,确保它有一个独立的事务,不受主业务的影响。

四、编程式事务管理

除了声明式事务,Spring还提供了编程式事务管理。

4.1 使用TransactionTemplate

咱们除了声明式事务,还能用编程式事务管理,那个TransactionTemplate挺好用的,简单明了。示例代码来一个:

@Service
public class OrderService {

    @Autowired
    private TransactionTemplate transactionTemplate;

    @Autowired
    private OrderDao orderDao;

    public void createOrder(final Order order) {
        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus status) {
                try {
                    // 业务逻辑
                    orderDao.insert(order); // 创建订单
                    // 其他操作...
                } catch (Exception e) {
                    status.setRollbackOnly(); // 标记为回滚
                    throw e;
                }
            }
        });
    }
}

注释:这块儿用了TransactionTemplate,它提供了编程式事务的封装。里面的方法有一个回调,事务操作就可以在这个回调里完成,发生异常时标记回滚。

4.2 使用PlatformTransactionManager

如果你想手动控制事务,那就得用PlatformTransactionManager,比TransactionTemplate更加灵活些,看看这个代码:

@Service
public class OrderService {

    @Autowired
    private PlatformTransactionManager transactionManager;

    @Autowired
    private OrderDao orderDao;

    public void createOrder(Order order) {
        // 定义事务属性
        DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
        definition.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        definition.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
        definition.setTimeout(30); // 设置超时时间,单位秒

        TransactionStatus status = transactionManager.getTransaction(definition);

        try {
            // 业务逻辑
            orderDao.insert(order);
            // 其他操作...

            transactionManager.commit(status); // 提交事务
        } catch (Exception e) {
            transactionManager.rollback(status); // 回滚事务
            throw e;
        }
    }
}

注释:这段代码显示了如何用PlatformTransactionManager来手动控制事务的开启、提交和回滚。适合那些需要高度定制化事务管理的场景。

五、事务高级特性

5.1 事务回滚规则

默认情况下,Spring事务只会在遇到运行时异常(RuntimeException)或错误(Error)时回滚,检查异常(Checked Exception)是不会触发回滚的。你可以通过@Transactional来指定哪些异常需要回滚。

自定义回滚异常

@Transactional(rollbackFor = {BusinessException.class, SQLException.class})
public void businessOperation() throws BusinessException {
    // 业务逻辑
    if (someCondition) {
        throw new BusinessException("业务异常");
    }
}

注释:你看,这样子自定义回滚的异常,业务出现问题就直接回滚,挺方便的,避免了错误数据的写入。

5.2 事务超时设置

想让事务超时自动回滚?可以这么做,直接设置个超时时间:

@Transactional(timeout = 30) // 单位秒
public void longRunningProcess() {
    // 这个方法执行时间超过30秒会触发超时回滚
}

注释:这块儿,设置了事务的超时,超过30秒就自动回滚。做长时间操作时,超时机制可以防止资源被锁死。

5.3 只读事务

有些操作就是查查数据,不做更新,那你就用readOnly=true,这样能优化性能,数据库能根据这个信息做一些优化:

@Transactional(readOnly = true)
public BigDecimal getAccountBalance(Long accountId) {
    // 只读操作,可以优化性能
    return accountDao.getBalance(accountId);
}

注释readOnly=true告诉Spring你这个事务只做查询操作,数据库可以做一些优化,比如减少锁的开销,性能杠杠的。

六、分布式事务

6.1 JTA与XA事务

分布式系统中,涉及多个数据库或者消息队列的时候,JTA和XA协议能帮你解决跨数据源的事务问题。Spring和JTA结合使用很方便。

配置示例

@Configuration
@EnableTransactionManagement
public class JtaTransactionConfig {

    @Bean
    public JtaTransactionManager transactionManager() {
        return new JtaTransactionManager(); // 使用JTA事务管理器
    }
}

注释:这个示例就是配置了JTA事务管理器,适合大规模分布式系统,能保证多数据源间的事务一致性。

6.2 Spring的分布式事务解决方案

Spring提供了几个方案来处理分布式事务,包括:

  1. XA协议:传统的两阶段提交协议。
  2. TCC模式:Try-Confirm-Cancel模式,分布式事务的经典模式。
  3. SAGA模式:长事务解决方案,基于补偿的方案。
  4. 本地消息表:最终一致性方案。
  5. Seata:阿里开源的分布式事务解决方案,解决分布式事务的痛点。

注释:分布式事务解决方案能让你在复杂系统中保证数据一致性,不同方案适应不同场景。

七、常见问题与解决方案

7.1 事务失效的常见场景

场景 原因 解决方案
方法非public Spring AOP限制 改为public方法
自调用 代理失效 注入自身或使用AopContext
异常被捕获 异常未传播 重新抛出或设置rollbackFor
数据库不支持 如MyISAM引擎 使用InnoDB引擎
传播行为设置错误 如NOT_SUPPORTED 调整传播行为

7.2 自调用问题解决方案

问题代码

@Service
public class OrderService {

    public void createOrder(Order order) {
        validateOrder(order);
        // 其他逻辑...
    }

    @Transactional
    public void validateOrder(Order order) {
        // 验证逻辑
    }
}

解决方案1:注入自身

@Service
public class OrderService {

    @Autowired
    private OrderService self; // 注入自身

    public void createOrder(Order order) {
        self.validateOrder(order); // 通过代理调用
        // 其他逻辑...
    }

    @Transactional
    public void validateOrder(Order order) {
        // 验证逻辑
    }
}

解决方案2:使用AopContext

@Service
public class OrderService {

    public void createOrder(Order order) {
        ((OrderService) AopContext.currentProxy()).validateOrder(order);
        // 其他逻辑...
    }

    @Transactional
    public void validateOrder(Order order) {
        // 验证逻辑
    }
}

八、性能优化与最佳实践

8.1 事务性能优化建议

  1. 尽量缩短事务范围:只在必要的地方使用事务。
  2. 合理设置隔离级别:不要过度使用SERIALIZABLE。
  3. 避免大事务:将大事务拆分为多个小事务。
  4. 合理使用只读事务:对查询操作使用readOnly=true。
  5. 注意异常处理:避免不必要的回滚。

8.2 事务最佳实践

  1. 事务注解应放在实现类上:而不是接口。
  2. 明确指定回滚异常:使用rollbackFor明确指定。
  3. 避免在事务中处理耗时操作:如RPC调用、IO操作等。
  4. 合理设置超时时间:避免长时间占用连接。
  5. 注意事务传播行为的选择:根据业务场景选择合适的传播行为。

九、完整案例演示

9.1 电商下单完整事务案例

@Service
public class OrderServiceImpl implements OrderService {

    @Autowired
    private OrderDao orderDao;

    @Autowired
    private ProductDao productDao;

    @Autowired
    private AccountDao accountDao;

    @Autowired
    private CouponDao couponDao;

    @Autowired
    private InventoryService inventoryService;

    @Transactional(propagation = Propagation.REQUIRED, 
                  isolation = Isolation.READ_COMMITTED,
                  timeout = 30,
                  rollbackFor = {BusinessException.class, RuntimeException.class})
    @Override
    public OrderResult createOrder(OrderRequest request) throws BusinessException {
        // 1. 验证订单基本信息
        validateOrderRequest(request);

        // 2. 锁定库存(使用REQUIRES_NEW传播行为,独立事务)
        inventoryService.lockInventory(request.getProductId(), request.getQuantity());

        // 3. 扣减账户余额
        deductAccountBalance(request.getUserId(), request.getTotalAmount());

        // 4. 使用优惠券(如果有)
        if (request.getCouponId() != null) {
            useCoupon(request.getUserId(), request.getCouponId());
        }

        // 5. 创建订单
        Order order = createOrderRecord(request);

        // 6. 发送创建订单事件(异步,不影响主事务)
        sendOrderCreatedEvent(order);

        return convertToResult(order);
    }

    private void validateOrderRequest(OrderRequest request) throws BusinessException {
        // 验证逻辑...
        if (request.getQuantity() <= 0) {
            throw new BusinessException("购买数量必须大于0");
        }
    }

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void lockInventory(Long productId, int quantity) throws BusinessException {
        // 锁定库存逻辑...
    }

    private void deductAccountBalance(Long userId, BigDecimal amount) throws BusinessException {
        // 扣减余额逻辑...
    }

    @Transactional(propagation = Propagation.MANDATORY)
    public void useCoupon(Long userId, Long couponId) throws BusinessException {
        // 使用优惠券逻辑...
    }

    private Order createOrderRecord(OrderRequest request) {
        // 创建订单记录逻辑...
    }

    private void sendOrderCreatedEvent(Order order) {
        // 异步发送事件...
    }
}

十、事务监控与调试

10.1 日志配置

在application.properties中添加:

# 开启Spring事务日志
logging.level.org.springframework.transaction.interceptor=TRACE
logging.level.org.springframework.jdbc.datasource.DataSourceTransactionManager=DEBUG
logging.level.org.springframework.orm.jpa.JpaTransactionManager=DEBUG

10.2 使用TransactionSynchronization

可以在事务的不同阶段执行回调:

@Transactional
public void businessMethod() {
    // 业务逻辑...

    TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
        @Override
        public void afterCommit() {
            // 事务提交后执行
            sendNotification();
        }

        @Override
        public void afterCompletion(int status) {
            // 事务完成后执行(status: 0=提交, 1=回滚)
            cleanUpResources();
        }
    });
}

总结

SpringBoot事务管理是开发企业级应用的重要部分。通过本文的全面介绍,你应该已经掌握了:

1、 事务的基本概念和ACID特性
2、 SpringBoot事务的配置和使用方式
3、 声明式和编程式事务的实现
4、 事务传播行为和隔离级别的详细解析
5、 高级特性和常见问题的解决方案
6、 分布式事务的基本概念
7、 性能优化和最佳实践

未经允许不得转载:搜云库 » SpringBoot事务管理详解:从基础到高级实战,全面掌握事务控制!

JetBrains 全家桶,激活、破解、教程

提供 JetBrains 全家桶激活码、注册码、破解补丁下载及详细激活教程,支持 IntelliJ IDEA、PyCharm、WebStorm 等工具的永久激活。无论是破解教程,还是最新激活码,均可免费获得,帮助开发者解决常见激活问题,确保轻松破解并快速使用 JetBrains 软件。获取免费的破解补丁和激活码,快速解决激活难题,全面覆盖 2024/2025 版本!

联系我们联系我们