0
点赞
收藏
分享

微信扫一扫

【大模型部署】在C# Winform中使用文心一言ERNIE-3.5 4K 聊天模型

一、前言

  Spring事务是指Spring框架中提供的事务管理功能,它可以帮助开发者简化事务管理的复杂性,提高代码的可维护性和可扩展性。本文将总结并分析Spring事务失效的各种场景,帮助你全面了解事务失效的原因和解决方案。

二、Spring事务失效的各种场景

1. 场景一:方法非public
代码展示:

@Service  
public class MyService {  
  
    @Transactional  
    void nonPublicMethod() {  
        // ... 业务逻辑  
    }  
}

原因分析:
  Spring AOP默认只对public方法进行拦截处理,因此非public方法上的@Transactional注解将不会被识别。

解决方案:
①. 将方法改为public。

②.让Spring支持非public方法


@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionAttributeSource transactionAttributeSource() {
  // 设置为false,这样protected及默认修饰的方法都将支持事务功能
  return new AnnotationTransactionAttributeSource(false) ;
}
开启Bean生效
GenericApplicationContext context = new GenericApplicationContext();
// 允许Bean覆盖,后面的BeanDefintion能覆盖前面的
// 我们定义的transactionAttributeSource bena能够覆盖系统默认的
context.setAllowBeanDefinitionOverriding(true) 

2.场景二:同一类中方法互相调用问题
代码展示:

@Service  
public class MyService {  
  
    @Transactional  
    public void outerMethod() {  
        innerMethod();  
    }  
  
    public void innerMethod() {  
        // ... 业务逻辑  
    }  
  
    // 假设在某个地方调用了outerMethod  
}

原因分析:
  在outerMethod中直接调用innerMethod属于自调用,不会通过代理,因此innerMethod的事务不会生效。

解决方案:
①.将innerMethod也加上@Transactional注解,
②.通过AopContext.currentProxy()获取代理对象进行调用。但通常不建议这么做,应重新设计代码结构。

 // 通过AopContext获取当前代理对象
  MyService proxy = (MyService )AopContext.currentProxy() ;
  proxy.innerMethod() ;

3.场景三:异常处理不当
代码展示:

@Service  
public class MyService {  
  
    @Transactional  
    public void myMethod() {  
        try {  
            // ... 业务逻辑,抛出Checked Exception  
        } catch (Exception e) {  
            // 处理异常,但没有重新抛出  
        }  
    }  
}

原因分析:
  默认情况下,Spring只会对运行时异常(RuntimeException)和Error进行事务回滚。如果捕获了异常并且没有重新抛出,那么事务管理器将不会知道异常的发生,因此不会触发回滚。

解决方案:
  确保在事务方法内部,所有需要触发回滚的异常都被抛出到方法外部,或者通过@Transactional的rollbackFor属性指定需要回滚的异常类型。

增加处理类型
@Transactional(rollbackFor = Exception.class)

抛出异常
} catch (Exception e) {
    e.printStackTrace() ;
    throw new Exception(e) ;
  }

4.场景四:数据源或事务管理器配置错误
代码展示:

@Configuration  
@EnableTransactionManagement  
public class DataSourceConfig {  
    // ... 数据源和事务管理器配置,可能存在错误  
}

原因分析:
  数据源或事务管理器配置错误,如数据源URL、用户名、密码错误,或者事务管理器与数据源未正确关联等。

解决方案:
  检查并修正数据源和事务管理器的配置。

5.场景五:传播类型设置错误
原因分析:
  以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。如果错误地设置为需要事务的传播类型,但你的方法实际上不应该在事务中运行,可能会导致性能问题或不必要的资源消耗。

代码展示:


@Service  
public class MyService {  
  
    @Transactional(propagation = Propagation.NOT_SUPPORTED)  
    public void myMethod() {  
        // ...  
    }  
}

解决方案:
  修改事务传播类型。

6.场景六:异步线程执行
原因分析:
  在一个事务方法中开启新的线程执行事务方法,因为主线程与子线程使用的不是同一个Connection对象,Spring事务执行会为每一个执行线程绑定一个Connection对象。

代码展示:

@Service  
public class MyService {  
  
    @Async  
    @Transactional  
    public void asyncMethod() {  
        // ...  
    }  
}

解决方案:
①.使用PROPAGATION_REQUIRES_NEW来确保在新的线程中开始一个新的事务,但是,请注意,这并不意味着这个新事务会与原始线程中的事务有任何关联。

②.手动管理事务,使用PlatformTransactionManager来手动管理事务

③.分布式事务

  总结:在本文中,深入探讨了Spring事务失效的各种情况。通过了解这些情况,我们可以更好地理解事务管理在Spring框架中的重要性,以及如何避免和解决事务失效的问题。

举报

相关推荐

0 条评论