关于事务回滚注解@Transactional

在使用Spring的@Transactional注解时,有时会出现事务失效的情况。这通常是由于一些常见的配置或使用错误引起的。以下是事务失效的原因和处理方法:

常见原因

  1. 方法可见性 @Transactional注解的方法必须是public的。Spring AOP代理只会拦截public方法,非public方法(如privateprotected或默认可见性的方法)将不会被代理,因此事务将不会生效。

    1
    2
    3
    4
    @Transactional
    public void myTransactionalMethod() {
        // Method logic
    }

  2. 方法内部调用 如果在同一个类内部调用一个被@Transactional注解的方法,该注解将失效。这是因为Spring AOP基于代理机制,内部方法调用不会经过代理对象。

    1
    2
    3
    public void nonTransactionalMethod() {
        myTransactionalMethod(); // This will not be transactional
    }

    解决方法:将事务方法移到另一个@Service类中,通过依赖注入调用。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    @Service
    public class MyService {
     
        @Autowired
        private AnotherService anotherService;
     
        public void nonTransactionalMethod() {
            anotherService.myTransactionalMethod();
        }
    }
     
    @Service
    public class AnotherService {
     
        @Transactional
        public void myTransactionalMethod() {
            // Method logic
        }
    }
  3. 代理机制 默认情况下,Spring AOP使用JDK动态代理或CGLIB代理。确保在Spring配置中启用了AOP支持:

    1
    2
    3
    4
    5
    @Configuration
    @EnableTransactionManagement
    public class AppConfig {
        // Configuration beans
    }
  4. 事务传播行为 不正确的事务传播行为设置可能导致事务失效。例如,@Transactional(propagation = Propagation.NOT_SUPPORTED)将导致事务在当前方法中被挂起。

    1
    2
    3
    4
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void myTransactionalMethod() {
        // Method logic
    }
  5. 异常处理 事务只会在方法抛出未捕获的运行时异常(RuntimeException)时回滚。受检异常(CheckedException)默认不会导致事务回滚。

    1
    2
    3
    4
    5
    6
    7
    8
    @Transactional
    public void myTransactionalMethod() throws Exception {
        try {
            // Method logic
        } catch (SpecificException e) {
            throw new RuntimeException(e); // Ensure rollback
        }
    }
  6. Spring Boot 和 JPA 配置 如果使用Spring Boot和JPA,确保正确配置了事务管理器。

    1
    2
    3
    4
    5
    6
    7
    @SpringBootApplication
    @EnableTransactionManagement
    public class Application {
        public static void main(String[] args) {
            SpringApplication.run(Application.class, args);
        }
    }

处理方法

  1. 检查方法可见性:确保被@Transactional注解的方法是public的。
  2. 避免内部方法调用:将事务方法移到另一个服务类中,通过依赖注入调用。
  3. 启用AOP支持:在Spring配置中启用事务管理和AOP支持。
  4. 正确设置传播行为:根据需求设置正确的事务传播行为。
  5. 正确处理异常:确保抛出未捕获的运行时异常以触发回滚。
  6. 检查配置:确保Spring Boot和JPA的配置正确。

示例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// Configuration class
@Configuration
@EnableTransactionManagement
public class DataSourceConfig {
    // DataSource and TransactionManager beans
}
 
// Service class
@Service
public class MyService {
 
    @Autowired
    private AnotherService anotherService;
 
    public void nonTransactionalMethod() {
        anotherService.myTransactionalMethod();
    }
}
 
@Service
public class AnotherService {
 
    @Transactional
    public void myTransactionalMethod() {
        // Method logic
    }
}

通过确保以上因素正确配置和使用,可以避免@Transactional失效的问题,确保事务管理生效。

 

posted @   阿迪di  阅读(89)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
Title
点击右上角即可分享
微信分享提示