@Transactional 失效总结

本文探讨了Spring AOP技术中@Transactional注解的使用限制,特别是针对静态方法、非public方法及自调用方法的情况。通过具体的代码示例说明了自调用方法时如何出现事务管理的问题。

@Transactional底层实现是SpringAOP技术,而SpringAOP技术是动态代理;

 

1. 静态方法;

2. 非public方法;

3. 自调用方法:即,一个类的一个方法调用自身另外一个方法,如下:

package com.cmb.service.impl;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.cmb.mapper.RoleMapper;
import com.cmb.pojo.Role;
import com.cmb.service.RoleService;

@Service
public class RoleServiceImpl implements RoleService {

	@Autowired
	private RoleMapper roleMapper = null;
	
	@Transactional(propagation = Propagation.REQUIRES_NEW, isolation = Isolation.READ_COMMITTED)
	public int insertRole(Role role) {
		return roleMapper.insertRole(role);
	}

	@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.READ_COMMITTED)
	public int insertRoleList(List<Role> roleList) {
     
		int count = 0;
		for(Role role : roleList){
			try{
				//调用自身类的方法,产生自调用问题
				count+= insertRole(role);
			}catch(Exception e){
				e.printStackTrace();
			}
		}
		return count;
	}
	
}

其中 ,

//调用自身类的方法,产生自调用问题
				count+= insertRole(role);

会出现此问题。

### @Transactional 注解失效原因及解决方案 @Transactional 注解在 Spring 框架中用于声明事务的边界,确保方法内的操作要么全部成功,要么全部失败(回滚)。然而,在某些情况下,@Transactional 注解可能不会按预期工作。以下是常见的失效原因及其解决办法: #### 1. 同一个类中方法调用导致注解失效 当一个带有 @Transactional 注解的方法被同一个类中的其他方法调用时,事务管理可能会失效。这是因为 Spring 使用 AOP 实现事务管理,而 AOP 的代理机制无法拦截类内部的方法调用[^3]。 **解决办法**:将方法拆分到不同的类中,或者通过显式地获取代理对象来调用目标方法。 ```java // 示例:通过代理对象调用方法 @Service public class MyService { @Autowired private ApplicationContext applicationContext; public void callTransactionalMethod() { MyService proxy = applicationContext.getBean(MyService.class); proxy.transactionalMethod(); } @Transactional public void transactionalMethod() { // 事务逻辑 } } ``` #### 2. 异常被捕获导致注解失效 如果方法中的异常被捕获并处理,Spring 事务管理器可能无法检测到异常,从而不会触发事务回滚[^2]。 **解决办法**:避免捕获异常或在捕获后重新抛出异常,以确保事务管理器能够检测到异常。 ```java @Transactional public void methodWithException() { try { // 数据库操作 throw new RuntimeException("Simulated exception"); } catch (Exception e) { // 记录日志 throw e; // 重新抛出异常 } } ``` #### 3. @Transactional 注解应用在非 public 方法上 @Transactional 注解只能应用于 public 方法上。如果将其应用于 private、protected 或 package-private 方法上,事务管理将失效[^4]。 **解决办法**:确保 @Transactional 注解仅应用于 public 方法。 ```java @Service public class MyService { @Transactional public void publicMethod() { // 正确使用 } @Transactional // 失效 private void privateMethod() { // 错误使用 } } ``` #### 4. @Transactional 注解属性 rollbackFor 设置错误 rollbackFor 属性用于指定哪些异常会触发事务回滚。如果设置不当,可能导致事务不按预期回滚[^5]。 **解决办法**:正确配置 rollbackFor 属性,确保涵盖所有需要回滚的异常类型。 ```java @Transactional(rollbackFor = {RuntimeException.class, SQLException.class}) public void methodWithRollback() { // 数据库操作 } ``` #### 5. @Transactional 注解属性 propagation 设置错误 propagation 属性定义了事务的传播行为。如果设置不当,可能导致事务无法正确传播或隔离[^5]。 **解决办法**:根据业务需求正确配置 propagation 属性。 ```java @Transactional(propagation = Propagation.REQUIRED) public void methodWithPropagation() { // 数据库操作 } ``` #### 6. 数据库引擎不支持事务 如果使用的数据库引擎(如 MySQL 的 MyISAM)不支持事务,即使正确配置了 @Transactional 注解,事务管理也会失效。 **解决办法**:选择支持事务的数据库引擎(如 MySQL 的 InnoDB)。 --- ### 总结 @Transactional 注解失效的主要原因包括:同一个类中方法调用、异常被捕获、注解应用在非 public 方法上、rollbackFor 属性设置错误、propagation 属性设置错误以及数据库引擎不支持事务。针对每种情况,可以通过调整代码结构、正确配置注解属性或选择合适的数据库引擎来解决问题。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值