在Spring Boot中手动管理数据库事务主要有以下几种方式:
1. 编程式事务管理
1.1 使用 TransactionTemplate
@Service
public class UserService {
@Autowired
private TransactionTemplate transactionTemplate;
@Autowired
private UserRepository userRepository;
public void createUserWithTransaction() {
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
try {
// 执行业务操作
User user1 = new User("张三", "zhangsan@example.com");
userRepository.save(user1);
User user2 = new User("李四", "lisi@example.com");
userRepository.save(user2);
// 如果需要回滚
// status.setRollbackOnly();
} catch (Exception e) {
status.setRollbackOnly();
throw e;
}
}
});
}
// 使用lambda表达式(推荐)
public void createUserWithTransactionLambda() {
transactionTemplate.execute(status -> {
try {
User user1 = new User("张三", "zhangsan@example.com");
userRepository.save(user1);
User user2 = new User("李四", "lisi@example.com");
userRepository.save(user2);
return null;
} catch (Exception e) {
status.setRollbackOnly();
throw e;
}
});
}
}
1.2 使用 PlatformTransactionManager
@Service
public class OrderService {
@Autowired
private PlatformTransactionManager transactionManager;
@Autowired
private OrderRepository orderRepository;
public void createOrderWithTransaction() {
// 定义事务属性
DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
definition.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
definition.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
definition.setTimeout(30); // 30秒超时
definition.setReadOnly(false);
// 开启事务
TransactionStatus status = transactionManager.getTransaction(definition);
try {
// 执行业务操作
Order order = new Order();
order.setOrderNo("ORD2023001");
order.setAmount(new BigDecimal("100.00"));
orderRepository.save(order);
// 提交事务
transactionManager.commit(status);
} catch (Exception e) {
// 回滚事务
transactionManager.rollback(status);
throw e;
}
}
}
2. 声明式事务管理(推荐)
2.1 使用 @Transactional 注解
@Service
@Transactional // 类级别的事务配置
public class ProductService {
@Autowired
private ProductRepository productRepository;
@Autowired
private InventoryRepository inventoryRepository;
// 方法级别的事务配置(会覆盖类级别的配置)
@Transactional(
propagation = Propagation.REQUIRED,
isolation = Isolation.READ_COMMITTED,
timeout = 30,
readOnly = false,
rollbackFor = Exception.class, // 所有异常都回滚
noRollbackFor = BusinessException.class // 业务异常不回滚
)
public void createProduct(ProductDTO dto) {
// 保存商品信息
Product product = convertToEntity(dto);
productRepository.save(product);
// 初始化库存
Inventory inventory = new Inventory();
inventory.setProductId(product.getId());
inventory.setStock(dto.getInitialStock());
inventoryRepository.save(inventory);
// 如果抛出RuntimeException,事务会自动回滚
// 如果抛出Exception,需要配置rollbackFor才会回滚
}
// 只读事务
@Transactional(readOnly = true)
public Product getProductDetail(Long id) {
return productRepository.findById(id).orElse(null);
}
// 嵌套事务
@Transactional(propagation = Propagation.NESTED)
public void updateProductStock(Long productId, Integer quantity) {
// ...
}
}
2.2 事务传播行为示例
@Service
public class ComplexService {
@Autowired
private UserService userService;
@Autowired
private OrderService orderService;
@Transactional
public void createOrderWithUser(Long userId, OrderDTO orderDTO) {
// REQUIRED(默认):如果当前没有事务,就新建一个事务
userService.validateUser(userId);
// REQUIRES_NEW:新建事务,如果当前存在事务,把当前事务挂起
orderService.createOrder(orderDTO);
// NESTED:嵌套事务,如果当前存在事务,则在嵌套事务内执行
// 嵌套事务是外部事务的子事务
}
}
3. 配置事务管理器
3.1 单数据源配置
@Configuration
@EnableTransactionManagement // 启用注解驱动的事务管理
public class TransactionConfig {
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
}
3.2 多数据源事务配置
@Configuration
@EnableTransactionManagement
public class MultiDataSourceTransactionConfig {
@Primary
@Bean(name = "primaryTransactionManager")
public PlatformTransactionManager primaryTransactionManager(
@Qualifier("primaryDataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
@Bean(name = "secondaryTransactionManager")
public PlatformTransactionManager secondaryTransactionManager(
@Qualifier("secondaryDataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
}
// 使用指定的事务管理器
@Service
public class MultiDataSourceService {
@Transactional("primaryTransactionManager")
public void primaryOperation() {
// 使用主数据源的事务
}
@Transactional("secondaryTransactionManager")
public void secondaryOperation() {
// 使用次数据源的事务
}
}
4. 事务监听器
@Component
public class TransactionEventListener {
// 事务提交后执行
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
public void handleAfterCommit(SomeEvent event) {
// 发送消息、记录日志等
}
// 事务回滚后执行
@TransactionalEventListener(phase = TransactionPhase.AFTER_ROLLBACK)
public void handleAfterRollback(SomeEvent event) {
// 补偿操作
}
}
@Service
public class EventPublisherService {
@Autowired
private ApplicationEventPublisher eventPublisher;
@Transactional
public void doBusiness() {
// 业务操作
// 发布事件
eventPublisher.publishEvent(new SomeEvent(this, data));
// 事务提交后,监听器会自动执行
}
}
5. 事务最佳实践
-
保持事务简短:尽量减少事务中的业务逻辑
-
避免在事务中进行远程调用:网络延迟会增加事务持有时间
-
合理设置事务隔离级别:根据业务需求选择合适级别
-
使用只读事务优化查询 :
@Transactional(readOnly = true) -
明确指定回滚异常 :
@Transactional(rollbackFor = Exception.class) -
避免在循环中开启事务:考虑批量操作
6. 常见问题解决
6.1 事务失效场景
@Service
public class TransactionIssueService {
// 问题1:在同一个类内部调用,@Transactional不会生效
public void methodA() {
methodB(); // @Transactional不会生效
}
@Transactional
public void methodB() {
// ...
}
// 解决方案:自注入
@Autowired
private TransactionIssueService self;
public void methodA2() {
self.methodB(); // 通过代理调用,事务生效
}
}
6.2 手动回滚部分操作
@Service
public class PartialRollbackService {
@Autowired
private TransactionTemplate transactionTemplate;
@Transactional
public void complexOperation() {
// 操作1:必须执行
saveLog();
try {
// 操作2:可能需要回滚
transactionTemplate.execute(status -> {
try {
riskyOperation();
return null;
} catch (Exception e) {
status.setRollbackOnly();
return null;
}
});
} catch (Exception e) {
// 只回滚riskyOperation,saveLog()已提交
log.error("Risky operation failed, but log saved", e);
}
}
}
根据具体业务场景选择合适的事务管理方式:
-
简单场景 :使用
@Transactional注解 -
复杂事务控制:使用编程式事务
-
需要精细控制 :使用
PlatformTransactionManager -
批量操作 :考虑使用
TransactionTemplate