javascript
Spring 事务失效的 8 种场景!
在日常工作中,如果對Spring的事務管理功能使用不當,則會造成Spring事務不生效的問題。而針對Spring事務不生效的問題,也是在跳槽面試中被問的比較頻繁的一個問題。
點擊上方卡片關注我
今天,我們就一起梳理下有哪些場景會導致Spring事務生效。
Spring事務不生效總覽
簡單來說,Spring事務會在幾種特定的場景下失效,如下圖所示。
1.數據庫不支持事務
Spring事務生效的前提是所連接的數據庫要支持事務,如果底層的數據庫都不支持事務,則Spring的事務肯定會失效。例如,如果使用的數據庫為MySQL,并且選用了MyISAM存儲引擎,則Spring的事務就會失效。
2.事務方法未被Spring管理
如果事務方法所在的類沒有加載到Spring IOC容器中,也就是說,事務方法所在的類沒有被Spring管理,則Spring事務會失效,示例如下。
public?class?ProductService?{@Autowiredprivate?ProductDao?productDao;@Transactional(propagation?=?Propagation.REQUIRES_NEW)public?void?updateProductStockCountById(Integer?stockCount,?Long?id){productDao.updateProductStockCountById(stockCount,?id);} }ProductService類上沒有標注@Service注解,Product的實例沒有加載到Spring IOC容器中,就會造成updateProductStockCountById()方法的事務在Spring中失效。
3.方法沒有被public修飾
如果事務所在的方法沒有被public修飾,此時Spring的事務會失效,例如,如下代碼所示。
@Service public?class?ProductService?{@Autowiredprivate?ProductDao?productDao;@Transactional(propagation?=?Propagation.REQUIRES_NEW)private?void?updateProductStockCountById(Integer?stockCount,?Long?id){productDao.updateProductStockCountById(stockCount,?id);} }雖然ProductService上標注了@Service注解,同時updateProductStockCountById()方法上標注了@Transactional(propagation = Propagation.REQUIRES_NEW)注解。
但是,由于updateProductStockCountById()方法為內部的私有方法(使用private修飾),那么此時updateProductStockCountById()方法的事務在Spring中會失效。
4.同一類中方法調用
如果同一個類中的兩個方法分別為A和B,方法A上沒有添加事務注解,方法B上添加了 @Transactional事務注解,方法A調用方法B,則方法B的事務會失效。例如,如下代碼所示。
@Service public?class?OrderService?{@Autowiredprivate?OrderDao?orderDao;@Autowiredprivate?ProductDao?productDao;public?void?submitOrder(){//生成訂單Order?order?=?new?Order();long?number?=?Math.abs(new?Random().nextInt(500));order.setId(number);order.setOrderNo("order_"?+?number);orderDao.saveOrder(order);//減庫存this.updateProductStockCountById(1,?1L);}@Transactional(propagation?=?Propagation.REQUIRES_NEW)public?void?updateProductStockCountById(Integer?stockCount,?Long?id){productDao.updateProductStockCountById(stockCount,?id);} }submitOrder()方法和updateProductStockCountById()方法都在OrderService類中,submitOrder()方法上沒有標注事務注解,updateProductStockCountById()方法上標注了事務注解,submitOrder()方法調用了updateProductStockCountById()方法,此時,updateProductStockCountById()方法的事務在Spring中會失效。
5.未配置事務管理器
如果在項目中沒有配置Spring的事務管理器,即使使用了Spring的事務管理功能,Spring的事務也不會生效。
例如,沒有在項目的配置類中配置如下代碼。
@Bean public?PlatformTransactionManager?transactionManager(DataSource?dataSource)?{return?new?DataSourceTransactionManager(dataSource); }此時,Spring的事務就會失效。
6.方法的事務傳播類型不支持事務
如果內部方法的事務傳播類型為不支持事務的傳播類型,則內部方法的事務在Spring中會失效。
例如,如下代碼所示。
@Service public?class?OrderService?{@Autowiredprivate?OrderDao?orderDao;@Autowiredprivate?ProductDao?productDao;@Transactional(propagation?=?Propagation.REQUIRED)public?void?submitOrder(){//生成訂單Order?order?=?new?Order();long?number?=?Math.abs(new?Random().nextInt(500));order.setId(number);order.setOrderNo("order_"?+?number);orderDao.saveOrder(order);//減庫存this.updateProductStockCountById(1,?1L);}@Transactional(propagation?=?Propagation.NOT_SUPPORTED)public?void?updateProductStockCountById(Integer?stockCount,?Long?id){productDao.updateProductStockCountById(stockCount,?id);} }由于updateProductStockCountById()方法的事務傳播類型為NOT_SUPPORTED,不支持事務,則updateProductStockCountById()方法的事務會在Spring中失效。
7.不正確的捕獲異常
不正確的捕獲異常也會導致Spring的事務失效,示例如下。
@Service public?class?OrderService?{@Autowiredprivate?OrderDao?orderDao;@Autowiredprivate?ProductDao?productDao;@Transactional(propagation?=?Propagation.REQUIRED)public?void?submitOrder(){//生成訂單Order?order?=?new?Order();long?number?=?Math.abs(new?Random().nextInt(500));order.setId(number);order.setOrderNo("order_"?+?number);orderDao.saveOrder(order);//減庫存this.updateProductStockCountById(1,?1L);}@Transactional(propagation?=?Propagation.REQUIRED)public?void?updateProductStockCountById(Integer?stockCount,?Long?id){try{productDao.updateProductStockCountById(stockCount,?id);int?i?=?1?/?0;}catch(Exception?e){logger.error("扣減庫存異常:",?e.getMesaage());}} }updateProductStockCountById()方法中使用try-catch代碼塊捕獲了異常,即使updateProductStockCountById()方法內部會拋出異常,但也會被catch代碼塊捕獲到,此時updateProductStockCountById()方法的事務會提交而不會回滾,并且submitOrder()方法的事務會提交而不會回滾,這就造成了Spring事務的回滾失效問題。
8.錯誤的標注異常類型
如果在@Transactional注解中標注了錯誤的異常類型,則Spring事務的回滾會失效,示例如下。
@Transactional(propagation?=?Propagation.REQUIRED) public?void?updateProductStockCountById(Integer?stockCount,?Long?id){try{productDao.updateProductStockCountById(stockCount,?id);}catch(Exception?e){logger.error("扣減庫存異常:",?e.getMesaage());throw?new?Exception("扣減庫存異常");} }在updateProductStockCountById()方法中捕獲了異常,并且在異常中拋出了Exception類型的異常,此時,updateProductStockCountById()方法事務的回滾會失效。
為何會失效呢?這是因為Spring中對于默認回滾的事務異常類型為RuntimeException,上述代碼拋出的是Exception異常。
默認情況下,Spring事務中無法捕獲到Exception異常,所以此時updateProductStockCountById()方法事務的回滾會失效。
此時可以手動指定updateProductStockCountById()方法標注的事務異常類型,如下所示。
@Transactional(propagation?=?Propagation.REQUIRED,rollbackFor?=?Exception.class)這里,需要注意的是:Spring事務注解@Transactional中的rollbackFor屬性可以指定 Throwable 異常類及其子類。
好了,今天就到這兒吧,我們下期見~~
總結
以上是生活随笔為你收集整理的Spring 事务失效的 8 种场景!的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 云计算应用迁移_应用迁移策略到云
- 下一篇: c语言用宏定义常量_使用宏定义常量以在C