以下是 Spring 事务管理的代码实现方式,涵盖 编程式事务 和 声明式事务 两种核心方式。
一、编程式事务管理
通过代码手动控制事务的提交和回滚,灵活但代码侵入性高。
1. 使用 TransactionTemplate
TransactionTemplate 是 Spring 提供的简化事务操作的工具类,适合单方法事务场景。
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.transaction.TransactionStatus;
@Service
public class UserService {
private final TransactionTemplate transactionTemplate;
private final UserRepository userRepository;
//构造器注入,其他方式也可以
public UserService(TransactionTemplate transactionTemplate, UserRepository userRepository) {
this.transactionTemplate = transactionTemplate;
this.userRepository = userRepository;
}
public void createUser(User user) {
// 通过 execute() 方法执行事务逻辑
transactionTemplate.execute(status -> {
try {
userRepository.save(user);
// 其他数据库操作(如更新关联表)
return "Success"; // 事务提交
} catch (Exception e) {
status.setRollbackOnly(); // 标记事务回滚
return "Failed: " + e.getMessage();
}
});
}
}
配置 TransactionTemplate:
@Configuration
public class TransactionConfig {
@Bean
public TransactionTemplate transactionTemplate(PlatformTransactionManager transactionManager) {
TransactionTemplate template = new TransactionTemplate();
template.setTransactionManager(transactionManager);
// 可选:设置事务属性(传播行为、隔离级别等)
template.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
template.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
return template;
}
}
2. 使用 PlatformTransactionManager
直接通过事务管理器控制事务,适合复杂事务逻辑(如多步骤操作)。
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
@Service
public class OrderService {
@Autowired
private PlatformTransactionManager transactionManager;
@Autowired
private OrderRepository orderRepository;
public void placeOrder(Order order) {
// 定义事务属性(传播行为、隔离级别等)
TransactionDefinition definition = new DefaultTransactionDefinition();
definition.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
definition.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
// 获取事务状态
TransactionStatus status = transactionManager.getTransaction(definition);
try {
orderRepository.save(order);
// 模拟其他业务操作(如扣减库存)
inventoryService.deductStock(order.getItemId(), order.getQuantity());
transactionManager.commit(status); // 提交事务
} catch (Exception e) {
transactionManager.rollback(status); // 回滚事务
throw new RuntimeException("Transaction failed", e);
}
}
}
二、声明式事务管理(推荐)
通过注解或 XML 配置声明事务规则,代码侵入性低,由 Spring AOP 代理实现。
1. 使用 @Transactional 注解
在方法或类上添加 @Transactional,由 Spring 自动管理事务生命周期。
启用事务管理(Spring Boot 自动配置,无需手动配置):
@SpringBootApplication
@EnableTransactionManagement // 显式启用(Spring Boot 默认自动启用)
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Service 层使用注解:
@Service
public class ProductService {
private final ProductRepository productRepository;
public ProductService(ProductRepository productRepository) {
this.productRepository = productRepository;
}
@Transactional(
propagation = Propagation.REQUIRED, // 默认值:当前有事务则加入,否则新建
isolation = Isolation.READ_COMMITTED, // 避免脏读
rollbackFor = Exception.class, // 指定回滚的异常类型
timeout = 30 // 事务超时时间(秒)
)
public void updateProduct(Product product) {
productRepository.update(product);
// 其他操作(如记录日志)
logService.logUpdate(product.getId());
}
@Transactional(readOnly = true) // 只读事务(优化性能)
public Product getProduct(Long id) {
return productRepository.findById(id);
}
}
2. 事务传播行为(Propagation)示例
场景:外层方法调用内层方法时,事务如何传递。
@Service
public class AccountService {
@Autowired
private UserService userService;
@Transactional(propagation = Propagation.REQUIRED)
public void transferMoney(Long fromId, Long toId, BigDecimal amount) {
userService.deductBalance(fromId, amount); // 调用另一个事务方法
userService.addBalance(toId, amount);
}
}
@Service
public class UserService {
@Transactional(propagation = Propagation.REQUIRED)
public void deductBalance(Long userId, BigDecimal amount) {
// 扣减余额
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void addBalance(Long userId, BigDecimal amount) {
// 独立事务执行(即使外层事务回滚,此操作仍提交)
}
}
3. 事务隔离级别(Isolation)示例
@Transactional(isolation = Isolation.SERIALIZABLE) // 最高隔离级别(避免幻读)
public void batchUpdateProducts(List<Product> products) {
products.forEach(product -> productRepository.update(product));
}
三、XML 配置方式(旧项目适用)
通过 XML 定义事务规则,适合非注解项目。
配置事务管理器:
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 定义事务通知 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="save*" propagation="REQUIRED"/>
<tx:method name="update*" propagation="REQUIRED"/>
<tx:method name="get*" read-only="true"/>
<tx:method name="*" propagation="SUPPORTS" read-only="true"/>
</tx:attributes>
</tx:advice>
<!-- 定义 AOP 切面 -->
<aop:config>
<aop:pointcut id="serviceMethods"
expression="execution(* com.example.service.*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="serviceMethods"/>
</aop:config>
四、事务失效的常见场景及解决
1. 自调用问题(同类方法调用)
问题:同一类中方法 A 调用方法 B,即使 B 有 @Transactional,事务也不会生效。
解决:
-
将方法 B 移到另一个类。
-
使用
AopContext.currentProxy()获取代理对象:@Transactional public void methodA() { ((UserService) AopContext.currentProxy()).methodB(); } @Transactional public void methodB() { // 事务生效 }
2. 异常未抛出
问题:默认只回滚 RuntimeException 和 Error,其他异常需显式配置。
解决:
@Transactional(rollbackFor = Exception.class) // 所有异常都触发回滚
public void update() throws Exception {
// ...
}
3. 非 public 方法
问题:@Transactional 注解在非 public 方法上无效。
解决:确保方法为 public。
总结
-
编程式事务:通过
TransactionTemplate或PlatformTransactionManager手动控制,适合复杂事务。 -
声明式事务:使用
@Transactional注解,简洁高效,推荐大多数场景。 -
关键配置:传播行为(
propagation)、隔离级别(isolation)、回滚规则(rollbackFor)。 -
常见陷阱:自调用、异常处理、非 public 方法。

1万+

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



