Spring 事务管理

Spring事务实现主要有两种方法:

1、编程式事务:通过显式的编码来控制事务的边界和行为,而不是依赖框架提供的声明式事务管理机制(如注解或XML配置)。这种方式提供了对事务更直接的控制,允许开发者精确地决定何时开启、提交或回滚事务。

优点:

​ 提供了极大的灵活性,开发者可以在代码中精确地控制事务的边界
​ 适用于需要对事务管理进行复杂逻辑控制的场景。

缺点:

​ 增加了代码量,使得业务逻辑与事务管理逻辑混杂在一起,降低了代码的可读性和可维护性。
​ 容易出错,因为事务的开启、提交和回滚都需要手动编码实现,增加了开发者的负担。

2、声明式事务:是一种在不修改业务逻辑代码的情况下,通过配置或注解来管理和控制事务的方式。它允许开发者以一种非侵入性的方式来定义事务边界,从而使代码更加简洁、清晰且易于维护。Spring框架提供了两种声明式事务管理的方式:基于XML的配置和基于注解的配置(推荐使用注解方式,因其更为直观和方便)

优点:

​ 主要通过配置或注解的方式实现,使事务管理与业务逻辑分离,提高了代码的清晰度和可维护性。
​ 可以通过AOP(面向切面编程)机制灵活地应用到不同的方法上,不需要修改业务逻辑代码。

缺点:

​ 相对于编程式事务管理,其灵活性较低。虽然可以通过一些高级配置满足复杂的事务需求,但在某些特定场景下可能不如编程式事务管理来得直接和强大。

声明式事务失效场景:

​在使用Spring声明式事务时,可能会遇到一些导致事务失效的场景。以下是一些常见的导致事务不生效的情况:

  1. 异常被捕获且未重新抛出
    如果在一个被@Transactional注解的方法内部捕获了异常但没有重新抛出,那么Spring将认为该方法执行成功,从而提交事务。这会导致即使发生了错误,事务也不会回滚。

  2. 方法不是public的
    @Transactional注解只能应用于public方法上。如果将此注解用在非public方法(如protected、private或包级私有)上,则事务管理不会生效。

  3. 自调用问题
    当一个类中的方法A调用同一个类中的另一个带有@Transactional注解的方法B时,由于这是通过this引用进行的直接调用,而不是通过代理对象,因此事务控制不会起作用。解决办法是让方法A也标记为@Transactional,或者通过ApplicationContext获取当前bean的代理实例来调用方法B。

  4. 异常类型不匹配
    默认情况下,只有unchecked exceptions (即继承自RuntimeException和Error的异常)才会触发事务回滚。如果你抛出了一个checked exception(例如IOException),除非你明确指定了rollbackFor属性,否则事务不会自动回滚。

  5. 配置错误

    • 没有正确配置<tx:annotation-driven />@EnableTransactionManagement
    • 事务管理器没有正确定义或注入到Spring容器中。
    • 使用了错误的事务管理器实现,比如对于JPA应该使用JpaTransactionManager,而对于Hibernate则应使用HibernateTransactionManager
  6. 数据库引擎不支持事务
    确保使用的数据库表类型支持事务。例如,在MySQL中,MyISAM存储引擎不支持事务,而InnoDB支持。

  7. 传播行为设置不当
    如果方法的事务传播行为设置为NOT_SUPPORTEDNEVERSUPPORTS等,那么这些设置可能导致事务不按预期工作。

  8. 异步方法
    在使用@Async注解的方法上同时使用@Transactional通常会导致事务失效,因为异步执行意味着方法调用发生在不同的线程中,而事务上下文不会跨线程传递。

  9. final方法
    如果方法被声明为final,那么Spring AOP无法为其创建代理,从而导致事务管理失效。

  10. 缺少事务管理器
    必须确保Spring容器中有且只有一个PlatformTransactionManager类型的bean,否则可能因为找不到合适的事务管理器而导致事务不生效。

posted @ 2025-08-05 00:36  log996  阅读(4)  评论(0)    收藏  举报