全部学科
NodeJS全栈
nodejs
Python全栈
python
小程序首页
📅 2026-05-18 8 分钟 ✍️ juanwangdev

事务超时与回滚规则

事务超时防止长时间占用数据库连接,回滚规则控制异常触发回滚的行为。

超时配置

基本用法

Java
// 超时时间30秒
@Transactional(timeout = 30)
public void processOrder(Order order) {
    // 超过30秒自动回滚
}

单位说明

Java
// timeout单位为秒
@Transactional(timeout = 60)  // 60秒
public void batchProcess() { }

// 超时后抛出TransactionTimedOutException

全局默认超时

YAML
# application.yml
spring:
  transaction:
    default-timeout: 30  # 全局默认30秒

XML配置

XML
<tx:advice id="txAdvice" transaction-manager="transactionManager">
    <tx:attributes>
        <tx:method name="batch*" timeout="120"/>
        <tx:method name="query*" timeout="10" read-only="true"/>
        <tx:method name="*" timeout="30"/>
    </tx:attributes>
</tx:advice>

超时计算方式

Java
事务开始时间: T0
当前时间: T
剩余时间: timeout - (T - T0)

当剩余时间 <= 0 时,抛出 TransactionTimedOutException

嵌套事务超时

Java
@Service
public class OuterService {

    @Autowired
    private InnerService innerService;

    @Transactional(timeout = 10)
    public void outer() {
        // 外层事务剩余10秒
        innerService.inner();  // 内层设置更长超时无效
    }
}

@Service
public class InnerService {

    @Transactional(timeout = 30)
    public void inner() {
        // 继承外层超时限制,实际只剩10秒
    }
}

嵌套事务超时取最小值,内层设置更长超时无效。

默认回滚规则

Java
// 默认:RuntimeException 和 Error 触发回滚
@Transactional
public void save(User user) {
    userRepository.save(user);
    throw new RuntimeException("异常");  // 回滚
}

@Transactional
public void save2(User user) throws Exception {
    userRepository.save(user);
    throw new Exception("受检异常");  // 不回滚!
}

rollbackFor - 指定回滚异常

Java
// 回滚所有Exception
@Transactional(rollbackFor = Exception.class)
public void save(User user) throws Exception {
    userRepository.save(user);
    throw new Exception("受检异常");  // 回滚
}

// 回滚多个异常类型
@Transactional(rollbackFor = {SQLException.class, IOException.class})
public void importData(String file) throws SQLException, IOException {
    // SQLException或IOException都会回滚
}

// 回滚自定义异常
@Transactional(rollbackFor = BusinessException.class)
public void process(Order order) {
    if (order.getAmount() < 0) {
        throw new BusinessException("金额异常");  // 回滚
    }
}

noRollbackFor - 排除回滚异常

Java
// 特定异常不回滚
@Transactional(noRollbackFor = BusinessException.class)
public void process() {
    throw new BusinessException("业务异常");  // 不回滚,提交事务
}

// 多个异常不回滚
@Transactional(noRollbackFor = {IllegalArgumentException.class,
                                 IllegalStateException.class})
public void validate() {
    throw new IllegalArgumentException("参数错误");  // 不回滚
}

rollbackForClassName - 使用类名

Java
// 使用全限定类名
@Transactional(rollbackForClassName = "java.lang.Exception")

// 多个类名
@Transactional(rollbackForClassName = {
    "java.sql.SQLException",
    "java.io.IOException"
})

// 不回滚类名
@Transactional(noRollbackForClassName = "com.example.BusinessException")

回滚规则组合

Java
// 回滚Exception,但排除BusinessException
@Transactional(
    rollbackFor = Exception.class,
    noRollbackFor = BusinessException.class
)
public void complex() {
    throw new SQLException();        // 回滚
    throw new BusinessException();   // 不回滚
}

实际应用场景

批量处理超时控制

Java
@Service
public class BatchService {

    @Transactional(timeout = 300)  // 5分钟超时
    public void batchImport(List<Data> dataList) {
        for (Data data : dataList) {
            dataDao.insert(data);
        }
    }
}

接口调用超时

Java
@Service
public class ApiService {

    @Transactional(timeout = 10)
    public void callExternalApi() {
        // 外部接口调用,防止长时间阻塞
        String result = httpClient.get("http://api.example.com/data");
        processResult(result);
    }
}

自定义异常回滚

Java
// 自定义异常
public class InsufficientBalanceException extends RuntimeException {
    public InsufficientBalanceException(String msg) {
        super(msg);
    }
}

@Service
public class AccountService {

    // 精确控制:只回滚余额不足异常
    @Transactional(rollbackFor = InsufficientBalanceException.class)
    public void transfer(Long fromId, Long toId, BigDecimal amount) {
        Account from = accountDao.findById(fromId);
        if (from.getBalance().compareTo(amount) < 0) {
            throw new InsufficientBalanceException("余额不足");
        }
        // 转账逻辑
    }
}

手动回滚

text
@Service
public class OrderService {

    @Autowired
    private TransactionStatus transactionStatus;

    @Transactional
    public void createOrder(Order order) {
        try {
            orderDao.insert(order);
            inventoryService.decrease(order.getItemId());
        } catch (Exception e) {
            // 手动标记回滚
            TransactionAspectSupport.currentTransactionStatus()
                .setRollbackOnly();
            throw e;
        }
    }
}

要点总结

  • timeout单位为秒,超时抛出TransactionTimedOutException
  • 嵌套事务超时取最小值
  • 默认只回滚RuntimeException和Error
  • rollbackFor = Exception.class实现全异常回滚
  • noRollbackFor排除特定异常的回滚
  • 手动回滚使用setRollbackOnly()

📝 发现内容有误?点击此处直接编辑

← 上一篇 事务的基本概念与ACID属性
下一篇 → 事务隔离级别
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库