Spring @Trancation注解

本文详细介绍了如何使用Spring框架的@Transactional注解来实现业务逻辑层的方法事务管理。包括注解的作用范围、事务传播特性、隔离级别、超时时间等关键属性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Spring可以通过注解@Transactional来为业务逻辑层的方法(调用DAO完成持久化动作)添加事务能力。

@Tranactional注解分析

  • 作用域:Transactional作用于类上表示类上所有的方法使用指定的事务管理策略,作用于方法表示该方法使用指定的事务管理策略;如果方法和类同时定义了@Tranactional注解,那么方法上定义的@Tranactional的属性覆盖类上定义的@Tranactional的属性
  • value: 用于匹配Spring中定义的tranactionManager的名字,默认是Spring中名称为transactionManager的事务管理器
  • propagation:事务传播属性,默认是Propagation.REQUIRED
  • isolation:事务隔离级别,默认是Isolation.DEFAULT,它是指数据库的默认隔离级别
  • timeout:事务超时时间,默认是TransactionDefinition.TIMEOUT_DEFAULT,它是指数据库的默认的事务超时时间
  • readOnly:设置该事务是否是只读事务;默认为false;
  • rollbackFor:用于设定需要进行回滚的异常类数组,默认只对运行时异常RuntimeException进行回滚。

PS:Spring中的用@Trancational注解标记的方法互相嵌套调用时与是否是同一个线程,同一个类没有关系。只要是Trancational方法,它就会根据propagation属性的值去决定是创建一个新的事务还是加入已存在的事务中。

具体参考文章:

http://blog.youkuaiyun.com/blueheart20/article/details/44654007

嵌套的@Trancation参考文章:

http://www.vito16.com/2015/10/07/spring-transaction-scope-bug.html

http://stamen.iteye.com/blog/1441794

转载于:https://www.cnblogs.com/userrain/p/5447887.html

### 关于事务被标记为仅回滚的原因及解决方案 #### 原因分析 事务被标记为仅回滚(`Transaction rolled back because it has been marked as rollback-only`),通常发生在以下几种情况中: 1. **异常被捕获但未重新抛出** 当内部事务发生异常时,如果该异常被外部捕获并吞掉,则 Spring 的事务管理器无法感知到异常的发生。此时,虽然内部事务已经被标记为只读状态,但由于外部事务并未收到通知,最终会在提交阶段引发 `UnexpectedRollbackException`[^3]。 2. **嵌套事务的不当配置** 如果多个服务方法都标注了 `@Transactional` 注解,并且这些方法之间存在调用关系,那么默认情况下它们会共享同一个事务上下文。一旦其中一个子事务发生了不可恢复的操作(如抛出运行时异常),整个父事务也会受到影响,进而导致父事务被标记为只读状态[^4]。 3. **异常类型不符合回滚策略** 默认情况下,只有 unchecked exception (继承自 `RuntimeException` 或者 `Error` 类型)才会触发事务自动回滚行为;而对于 checked exception 则不会主动触发回滚机制。因此,如果没有显式声明支持某些特定类型的异常作为回滚条件(通过参数 `rollbackFor` 配置),即使出现了预期之外的情况也不会真正影响到当前事务的状态变化过程[^5]。 --- #### 解决方案 为了有效应对上述提到的各种潜在问题,可以采取如下措施来优化现有代码逻辑以及调整相关配置选项: 1. **合理设置传播特性** 使用合适的事务传播属性可以帮助我们更好地控制不同层次间如何相互作用及其各自独立性的保持程度。对于那些可能需要单独处理失败情形或者希望保留原有操作记录而不干扰整体流程的部分功能模块来说,推荐将其定义为具有嵌套特性的子事务单元。例如: ```java @Transactional(propagation = Propagation.NESTED, rollbackFor = Exception.class) public void nestedMethod() { // 子事务的具体实现细节... } ``` 这样一来,即便某个局部区域产生了错误状况,也不至于波及其他关联部分的工作成果[^1]。 2. **明确指定回滚规则** 显式地告诉框架哪些种类别的异常应当引起关注并促使相应的清理动作被执行是非常重要的一步。可以通过向 `@Transactional` 添加额外参数的方式来达成这一目标,比如下面的例子展示了怎样让任何 Throwable 实例都能成为终止信号源之一: ```java @Transactional(rollbackFor = {SQLException.class, IOException.class}) public void criticalOperation() throws SQLException, IOException { // 可能抛出 SQL 错误或 IO 故障的关键业务环节... } ``` 此外还可以利用反义词形式排除不需要考虑的情形列表,从而进一步细化定制化需求[^5]。 3. **改进异常处理机制** 在实际开发过程中难免遇到各种意外事件的发生概率增加的趋势,这就要求我们必须更加谨慎对待每一个可能出现风险的地方。一方面要尽量减少不必要的复杂度堆积现象以免造成难以追踪定位的问题根源所在之处;另一方面也要充分考虑到后续维护人员的理解成本高低差异等因素的影响效果。具体做法包括但不限于以下几个方面: - 不随意忽略已知的异常信息; - 对重要日志内容进行妥善保存以便事后审查分析之需; - 提供清晰易懂的帮助文档说明常见故障排查技巧等等[^3]. --- ### 示例代码 以下是基于以上讨论的一个综合改进建议版本示例: ```java @Service public class OrderService { @Autowired private PaymentService paymentService; /** * 主订单创建服务方法 */ @Transactional(rollbackFor = Exception.class) public void createOrder(Order order) throws BusinessException { try { saveOrder(order); paymentService.chargePayment(order.getOrderId(), order.getAmount()); } catch (BusinessException be) { log.error("Failed to process order creation", be); throw be; } finally { updateStatusIfNecessary(order); } } } @Service public class PaymentService { /** * 支付扣款服务方法 */ @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class) public void chargePayment(Long orderId, BigDecimal amount) throws BusinessException { if (!validatePaymentConditions(orderId)) { throw new BusinessException("Invalid payment conditions"); } deductBalance(amount); // Simulate balance deduction logic here. } } ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值