• Spring中事务的几种失效场景


    当使用Spring进行事务管理时,有一些情况可能会导致事务失效。以下是一些常见的情况,以及每种情况的例子:

    1. 同一个类中的方法调用

      • 情况:如果在同一个类中的一个带有 @Transactional 注解的方法直接调用另一个带有 @Transactional 注解的方法,事务注解可能会失效。
      • 示例
        @Service
        public class MyService {
        
            @Autowired
            private MyRepository myRepository;
        
            @Transactional
            public void methodA() {
                // some business logic
                methodB(); // Calling another @Transactional method in the same class
            }
        
            @Transactional
            public void methodB() {
                // some other business logic
            }
        }
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        在这个例子中,methodA() 中调用了 methodB(),由于它们都在同一个类中且都被 @Transactional 注解修饰,事务注解可能会失效。
    2. 异常被吞噬

      • 情况:如果在事务方法内部捕获了异常并未重新抛出,事务可能不会回滚。
      • 示例
        @Service
        public class MyService {
        
            @Autowired
            private MyRepository myRepository;
        
            @Transactional
            public void methodC() {
                try {
                    // some business logic
                } catch (Exception e) {
                    // Exception is caught but not rethrown
                }
            }
        }
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        在这个例子中,如果在 methodC() 中的业务逻辑出现异常但被捕获后不再抛出,事务可能不会回滚,因为异常被吞噬了。
    3. 异步方法

      • 情况:如果在异步方法上使用了 @Transactional 注解,事务可能不会生效,因为 Spring 无法拦截异步方法的调用。
      • 示例
        @Service
        public class MyService {
        
            @Autowired
            private MyRepository myRepository;
        
            @Async
            @Transactional
            public void asyncMethod() {
                // asynchronous method logic
            }
        }
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        在这个例子中,asyncMethod() 被标记为异步方法,并且同时使用了 @Transactional 注解,但由于 Spring 无法拦截异步方法的调用,事务可能不会生效。

    除此之外,下面这几种情况也会导致事务失效:

    1. 确保事务方法的独立性:保证每个事务方法都是相对独立的,不依赖于同一个类中的其他带有 @Transactional 注解的方法。例如:
    @Service
    public class MyService {
     
        @Autowired
        private MyRepository myRepository;
     
        @Transactional
        public void methodA() {
            // some business logic
        }
    
        @Transactional
        public void methodB() {
            // some other business logic
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    在这个例子中,methodA()methodB() 分别是独立的事务方法,彼此之间没有相互调用的关系,因此不会导致事务失效

    1. 正确处理异常:在事务方法中正确处理异常,并在必要时重新抛出异常以触发事务回滚。例如:
    @Service
    public class MyService {
     
        @Autowired
        private MyRepository myRepository;
     
        @Transactional
        public void methodC() {
            try {
                // some business logic
            } catch (Exception e) {
                // Log the exception or handle it appropriately
                throw new RuntimeException("Exception occurred in methodC", e); // Re-throw the exception to trigger transaction rollback
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    在这个例子中,如果 methodC() 中的业务逻辑出现异常,异常会被捕获并重新抛出,从而触发事务回滚,确保数据的一致性。

    1. 避免在异步方法上使用事务:避免在异步方法上使用 @Transactional 注解。例如:
    @Service
    public class MyService {
     
        @Autowired
        private MyRepository myRepository;
     
        @Async
        public void asyncMethod() {
            // asynchronous method logic without @Transactional annotation
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    在这个例子中,asyncMethod() 是一个异步方法,没有使用 @Transactional 注解,从而避免了事务失效的可能性。

  • 相关阅读:
    SPOOL、SQLLOADER数据导出导入的一点小总结
    第2章 第一个Spring Boot项目
    企业公众号怎么做内容?这四个阶段要做好
    数据结构——双链表
    [Python]跟着代码去学习---二维码1:文字生成二维码
    入行数字IC验证后会做些什么?需要哪些必备技能?
    05 常见微服务项目结构
    【算法练习Day43】最佳买卖股票时机含冷冻期&&买卖股票的最佳时机含手续费
    数字电路计算器
    交互设计师必须知道的五大交互设计流程
  • 原文地址:https://blog.csdn.net/hello_boyu/article/details/138171897