Spring事務失效的原因


一. mysql 存儲引擎不支持事務

二. 數據源沒有配置事務管理器

@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {
    return new DataSourceTransactionManager(dataSource);
}

如上面所示,當前數據源若沒有配置事務管理器,那也是白搭!

三. 沒有被 Spring 管理 。

//@Service
public class OrderServiceImpl implements OrderService {

    @Transactional
    public void updateOrder(Order order) {
        //update order
    }

}

 @Service 注掉,這個類就不會被加載成 Bean,這個類就不會被 Spring 管理了,事務自然就失效了。

四. 方法不是 public 的(?)

 @Transactional 只能用於 public 的方法上,否則事務不會失效,如果要用在非 public 方法上,可以開啟 AspectJ 代理模式。 spring的聲明式事務是基於代理模式的。由於java繼承時, 不能重寫 private , final , static 修飾的方法。private 方法, final 方法 和 static 方法都沒有事務支持。原因,pring的聲明式事務是基於代理模式的。 所以, 所有的 private 方法, final 方法 和 static 方法 都無法 直接 添加spring的事務管理功能。

private 方法無法添加事務管理. final 方法無法添加事務管理. static 方法無法添加事務管理. 當繞過代理對象, 直接調用添加事務管理的方法時, 事務管理將無法生效.?

五. 傳播類型不支持事務

@Service
public class OrderServiceImpl implements OrderService {

    @Transactional
    public void update(Order order) {
        updateOrder(order);
    }

    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public void updateOrder(Order order) {
        // update order
    }

}

以非事務方式執行操作,如果當前存在事務,就把當前事務掛起。?

六. 異常被吃了

@Service
public class OrderServiceImpl implements OrderService {

    @Transactional
    public void updateOrder(Order order) {
        try {
           
        } catch {

        }
    }
}

把異常吃了,然后又不拋出來,事務怎么回滾吧!

七.拋出異常類型不對

@Service
public class OrderServiceImpl implements OrderService {

    @Transactional
    public void updateOrder(Order order) {
        try {
           
        } catch {
            throw new Exception("更新錯誤");
        }
    }
}

這樣事務也是不生效的,因為默認回滾的是:RuntimeException。
如果你想觸發其他異常的回滾,需要在注解上配置一下,
如:@Transactional(rollbackFor = Exception.class)
這個配置僅限於 Throwable 異常類及其子類。

八. 自身(this)調用問題

@Controller
public class TestController {
    @Autowired
    private TestService testService;
    @GetMapping("/test")
    public void test(){

        testService.methodA();

    }
    
}
1. 事務失效。
因為,spring的事務實現是使用了代理類來實現,而這里的this.methodA(),並沒有走TestService(被spring容器管理)的代理類,所以事務會失效。
@Service
public class TestService {

    /**
     * 這里調用methodB() 的事務將會失效
     */
    public void methodA(){
        this.methodB();
    }
    
    @Transactional
    public void methodB(){

    }
}
解決
方法1:把methodA()和methodB()分別放到不同的類里。
方法2:自己注入自己,用注入的實例調用。
方法3:獲取代理類,利用代理類調用自己類的方法
方法2代碼
@Service
public class TestService {

    @Autowired
    private TestService testService;
    
    /**
     * 這里調用methodB() 的事務將會生效
     */
    public void methodA(){
        testService.methodB();
    }
    @Transactional
    public void methodB(){

    }

}
方法3代碼
@Service
public class TestService { /** * 這里調用methodB() 的事務將會生效 */ public void methodA(){ ((TestService)AopContext.currentProxy()).methodB(); } @Transactional public void methodB(){ } }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM