事务超时与回滚规则
事务超时防止长时间占用数据库连接,回滚规则控制异常触发回滚的行为。
超时配置
基本用法
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()
📝 发现内容有误?点击此处直接编辑