You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring事务:@Transactional回滚配置选Exception还是RuntimeException?

Spring Transaction Rollback: Choosing Between rollbackFor = Exception.class and Default RuntimeException Behavior

Great question! Let’s break this down clearly based on how Spring handles transaction rollbacks—this is a super common point of confusion for developers working with Spring transactions.

First, Understand Spring's Default Rule

By default, Spring’s @Transactional annotation only triggers a transaction rollback for:

  • Unchecked exceptions: RuntimeException and all its subclasses (like NullPointerException, IllegalArgumentException)
  • Errors: Serious system-level issues like OutOfMemoryError

It does NOT automatically roll back for checked exceptions (classes that extend Exception directly, not RuntimeException—think custom business exceptions you define as checked exceptions).

When to Use Which Configuration

1. Go with @Transactional(rollbackFor = Exception.class)

Use this when you want every exception (checked AND unchecked) to trigger a rollback. This is necessary if:

  • Your code throws custom checked exceptions (e.g., public class BadRequestException extends Exception)
  • You need those checked exceptions to undo any database changes made earlier in the transaction

For example, if you have a method that saves an order first, then throws a checked exception when validation fails—without rollbackFor = Exception.class, the saved order would stay in the database, which is almost never what you want.

2. Stick with Default @Transactional (No rollbackFor Setting)

Use this default behavior when you only want unchecked exceptions/Errors to trigger rollbacks. This works great if:

  • All your custom business exceptions extend RuntimeException (e.g., public class BadRequestException extends RuntimeException)
  • You treat checked exceptions as "expected" business outcomes that don’t require undoing database changes (though this is less common in practice)

Spring’s default rule will automatically roll back the transaction whenever an unchecked exception is thrown, so no extra configuration is needed here.

Code Examples to Illustrate

Example 1: Checked Exception + rollbackFor = Exception.class

// Custom checked exception
public class BadRequestException extends Exception {
    public BadRequestException(String message) {
        super(message);
    }
}

@Service
public class OrderService {
    @Transactional(rollbackFor = Exception.class)
    public void createOrder(OrderDto orderDto) throws BadRequestException {
        // Step 1: Save order to database
        orderRepository.save(orderDto);
        
        // Validation fails—throw checked exception
        if (orderDto.getAmount() <= 0) {
            throw new BadRequestException("Order amount cannot be negative");
        }
        
        // Step 2: Deduct stock (never runs if exception is thrown)
        stockRepository.decreaseStock(orderDto.getProductId(), orderDto.getQuantity());
    }
}

Without rollbackFor = Exception.class, the saved order would remain in the database even after the exception is thrown. Adding this setting ensures the transaction rolls back entirely.

Example 2: Unchecked Exception + Default @Transactional

// Custom unchecked exception
public class BadRequestException extends RuntimeException {
    public BadRequestException(String message) {
        super(message);
    }
}

@Service
public class OrderService {
    @Transactional // No extra config needed
    public void createOrder(OrderDto orderDto) {
        // Step 1: Save order to database
        orderRepository.save(orderDto);
        
        // Validation fails—throw unchecked exception
        if (orderDto.getAmount() <= 0) {
            throw new BadRequestException("Order amount cannot be negative");
        }
        
        // Step 2: Deduct stock (never runs if exception is thrown)
        stockRepository.decreaseStock(orderDto.getProductId(), orderDto.getQuantity());
    }
}

Here, Spring automatically rolls back the transaction when BadRequestException is thrown, since it’s a subclass of RuntimeException. The saved order is removed from the database as expected.

Key Takeaway

  • Choose @Transactional(rollbackFor = Exception.class) if you need all exceptions (checked and unchecked) to trigger rollbacks, especially when working with custom checked exceptions.
  • Use the default @Transactional if your custom exceptions are unchecked (extend RuntimeException) or you only want system/unexpected exceptions to roll back transactions.

内容的提问来源于stack exchange,提问作者k.sh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 10:12:21