事务简介
事务(Transaction)是基于关系型数据库(RDBMS)的企业级应用的重要组成部分。在软件开发领域,事务扮演者十分重要的角色,用来确保应用程序数据的完整性和一致性。
事务具有 4 个特性:原子性、一致性、隔离性和持久性,简称为 ACID 特性。
原子性(Atomicity):一个事务是一个不可分割的工作单位,事务中包括的动作要么都做要么都
不做。
一致性(Consistency):事务必须保证数据库从一个一致性状态变到另一个一致性状态,一致性
和原子性是密切相关的。
隔离性(Isolation):一个事务的执行不能被其它事务干扰,即一个事务内部的操作及使用的数据
对并发的其它事务是隔离的,并发执行的各个事务之间不能互相打扰。
持久性(Durability):持久性也称为永久性,指一个事务一旦提交,它对数据库中数据的改变就
是永久性的,后面的其它操作和故障都不应该对其有任何影响
在 Spring Boot 中使用事务管理非常方便,Spring 提供了声明式和编程式两种事务管理方式,推荐使用声明式事务(基于注解)。以下是详细的使用方法:
1. 启用事务管理
在 Spring Boot 主类上添加@EnableTransactionManagement注解(实际上 Spring Boot 默认已启用,此步骤通常可省略):
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@SpringBootApplication
@EnableTransactionManagement // 启用事务管理(可选,Spring Boot默认已启用)
public class YourApplication {
public static void main(String[] args) {
SpringApplication.run(YourApplication.class, args);
}
}
2. 声明式事务(推荐)
在 Service 层的方法上添加@Transactional注解:
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
// 整个方法在一个事务中执行
@Transactional
public void transferMoney(Long fromUserId, Long toUserId, double amount) {
// 查询账户
User fromUser = userRepository.findById(fromUserId).orElseThrow();
User toUser = userRepository.findById(toUserId).orElseThrow();
// 转账操作
fromUser.setBalance(fromUser.getBalance() - amount);
toUser.setBalance(toUser.getBalance() + amount);
// 保存修改
userRepository.save(fromUser);
userRepository.save(toUser);
// 如果中间发生异常,所有操作都会回滚
if (amount > 1000) {
throw new RuntimeException("金额过大,模拟异常");
}
}
}
3. 事务属性配置
@Transactional注解支持多种属性配置:
@Transactional(
propagation = Propagation.REQUIRED, // 传播行为
isolation = Isolation.READ_COMMITTED, // 隔离级别
timeout = 30, // 超时时间(秒)
readOnly = false, // 是否只读
rollbackFor = {Exception.class} // 指定需要回滚的异常类型
)
public void complexOperation() {
// ...
}
4. 事务传播行为
控制事务如何与现有事务交互,常见的传播行为:
REQUIRED(默认):如果存在事务则加入,否则创建新事务。
REQUIRES_NEW:总是创建新事务,挂起当前事务。
SUPPORTS:支持当前事务,若无则以非事务方式执行。
NOT_SUPPORTED:以非事务方式执行,挂起当前事务。
MANDATORY:必须在现有事务中执行,否则抛出异常。
5. 异常处理与回滚
默认情况下,Spring 事务只对RuntimeException及其子类触发回滚。
可通过rollbackFor属性指定需要回滚的异常类型:
@Transactional(rollbackFor = {Exception.class}) // 所有异常都回滚
6. 编程式事务(较少使用)
通过TransactionTemplate或PlatformTransactionManager手动管理事务:
@Autowired
private TransactionTemplate transactionTemplate;
public void manualTransaction() {
transactionTemplate.execute(status -> {
try {
// 业务逻辑
return true;
} catch (Exception e) {
status.setRollbackOnly(); // 手动回滚
return false;
}
});
}
7. 多数据源事务管理
如果使用多个数据源,需要配置JtaTransactionManager(JTA 分布式事务)或使用@Transactional的value属性指定事务管理器:
@Transactional("secondTransactionManager")
public void secondDbOperation() {
// ...
}
注意:
- 事务边界:
@Transactional注解的方法必须是 public,且只能被外部调用触发。 - 异常捕获:若在事务方法内部捕获异常而不抛出,可能导致事务不回滚。
- 嵌套事务:慎用嵌套事务,避免
REQUIRES_NEW导致性能问题。 - 只读事务:对只读操作设置
readOnly = true提升性能。
示例:多操作原子性保证
@Service
public class OrderService {
@Autowired
private OrderRepository orderRepository;
@Autowired
private InventoryRepository inventoryRepository;
@Transactional
public void createOrder(Order order) {
// 扣减库存
inventoryRepository.decreaseStock(order.getProductId(), order.getQuantity());
// 创建订单
orderRepository.save(order);
// 如果后续操作失败,库存扣减和订单创建都会回滚
if (order.getAmount() > 10000) {
throw new BusinessException("订单金额过大");
}
}
}
398

被折叠的 条评论
为什么被折叠?



