事务相关问题
目录
1.在一个bean中,一个无事务的方法调用有事务的方法,事务失效
2.在一个事务中进行数据源的切换不生效
3.一个有事务的方法调用另一个有事务的方法,如果在第二个方法中出现异常,事务回滚,然后在第一个方法中,没有判断第二个方法的返回值,直接进行事务的提交,这时会报错,因为事务已经回滚了,不能进行提交
1.在一个bean中,一个无事务的方法调用有事务的方法,事务失效
原因是在一个类中调用,使用this调用,this指的是当前原始对象的实例,而非代理对象
解决方法:将要添加事务的方法写在其他bean中,方法上添加事务,然后注入进行进行调用
@Service
public class UserService {public void methodA() {// 无事务方法this.methodB(); // 直接调用,事务失效}@Transactionalpublic void methodB() {// 有事务方法// 事务失效原因:this指向原始对象,而不是代理对象// 解决方案:通过注入的代理对象调用}
}// 正确写法
@Service
public class UserService {@Autowiredprivate UserService self; // 注入代理对象public void methodA() {self.methodB(); // 通过代理对象调用,事务生效}@Transactionalpublic void methodB() {// 有事务方法}
}
2.在一个事务中进行数据源的切换不生效
因为开启事务后是不能进行动态数据源的切换的
事务内是不支持进行数据源的切换的,一旦开启事务,这个事务只能对应一个数据源
解决方法:规划好方法的逻辑,不在事务内进行数据源的切换
@Service
public class UserService {@Autowiredprivate DataSource dataSource;@Transactionalpublic void method() {// 开启事务try {// 业务操作1// 尝试切换数据源DynamicDataSourceContextHolder.setDataSource("slave");// 此时切换数据源不会生效,因为事务已经开启// 事务会继续使用原来的数据源// 业务操作2} finally {DynamicDataSourceContextHolder.clear();}}
}// 正确写法:在事务方法之前切换数据源
@Service
public class UserService {@Autowiredprivate UserService self;public void method() {// 先切换数据源DynamicDataSourceContextHolder.setDataSource("slave");try {// 再开启事务self.transactionalMethod();} finally {DynamicDataSourceContextHolder.clear();}}@Transactionalpublic void transactionalMethod() {// 事务方法}
}
3.一个有事务的方法调用另一个有事务的方法,如果在第二个方法中出现异常,事务回滚,然后在第一个方法中,没有判断第二个方法的返回值,直接进行事务的提交,这时会报错,因为事务已经回滚了,不能进行提交
解决方法:可以在第二个方法中开启一个新事物,这样两个事务互补干扰
也可以在第二个方法中不添加事务,直接使用方法一的事务,如果方法二异常,则在方法一中进行判断,进行事务的操作