<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Spring 事務(wù)失效的 8 種場(chǎng)景!

          共 5081字,需瀏覽 11分鐘

           ·

          2021-12-26 00:01

          在日常工作中,如果對(duì)Spring的事務(wù)管理功能使用不當(dāng),則會(huì)造成Spring事務(wù)不生效的問(wèn)題。而針對(duì)Spring事務(wù)不生效的問(wèn)題,也是在跳槽面試中被問(wèn)的比較頻繁的一個(gè)問(wèn)題。

          點(diǎn)擊上方卡片關(guān)注我

          今天,我們就一起梳理下有哪些場(chǎng)景會(huì)導(dǎo)致Spring事務(wù)生效。


          Spring事務(wù)不生效總覽

          簡(jiǎn)單來(lái)說(shuō),Spring事務(wù)會(huì)在幾種特定的場(chǎng)景下失效,如下圖所示。


          1.數(shù)據(jù)庫(kù)不支持事務(wù)

          Spring事務(wù)生效的前提是所連接的數(shù)據(jù)庫(kù)要支持事務(wù),如果底層的數(shù)據(jù)庫(kù)都不支持事務(wù),則Spring的事務(wù)肯定會(huì)失效。例如,如果使用的數(shù)據(jù)庫(kù)為MySQL,并且選用了MyISAM存儲(chǔ)引擎,則Spring的事務(wù)就會(huì)失效。

          2.事務(wù)方法未被Spring管理

          如果事務(wù)方法所在的類(lèi)沒(méi)有加載到Spring IOC容器中,也就是說(shuō),事務(wù)方法所在的類(lèi)沒(méi)有被Spring管理,則Spring事務(wù)會(huì)失效,示例如下。

          public?class?ProductService?{
          ?@Autowired
          ?private?ProductDao?productDao;

          ?@Transactional(propagation?=?Propagation.REQUIRES_NEW)
          ?public?void?updateProductStockCountById(Integer?stockCount,?Long?id){
          ??productDao.updateProductStockCountById(stockCount,?id);
          ?}
          }

          ProductService類(lèi)上沒(méi)有標(biāo)注@Service注解,Product的實(shí)例沒(méi)有加載到Spring IOC容器中,就會(huì)造成updateProductStockCountById()方法的事務(wù)在Spring中失效。

          3.方法沒(méi)有被public修飾

          如果事務(wù)所在的方法沒(méi)有被public修飾,此時(shí)Spring的事務(wù)會(huì)失效,例如,如下代碼所示。

          @Service
          public?class?ProductService?{
          ?@Autowired
          ?private?ProductDao?productDao;

          ?@Transactional(propagation?=?Propagation.REQUIRES_NEW)
          ?private?void?updateProductStockCountById(Integer?stockCount,?Long?id){
          ??productDao.updateProductStockCountById(stockCount,?id);
          ?}
          }

          雖然ProductService上標(biāo)注了@Service注解,同時(shí)updateProductStockCountById()方法上標(biāo)注了@Transactional(propagation = Propagation.REQUIRES_NEW)注解。

          但是,由于updateProductStockCountById()方法為內(nèi)部的私有方法(使用private修飾),那么此時(shí)updateProductStockCountById()方法的事務(wù)在Spring中會(huì)失效。

          4.同一類(lèi)中方法調(diào)用

          如果同一個(gè)類(lèi)中的兩個(gè)方法分別為A和B,方法A上沒(méi)有添加事務(wù)注解,方法B上添加了 @Transactional事務(wù)注解,方法A調(diào)用方法B,則方法B的事務(wù)會(huì)失效。例如,如下代碼所示。

          @Service
          public?class?OrderService?{

          ?@Autowired
          ?private?OrderDao?orderDao;

          ?@Autowired
          ?private?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);
          ??//減庫(kù)存
          ??this.updateProductStockCountById(1,?1L);
          ?}

          ?@Transactional(propagation?=?Propagation.REQUIRES_NEW)
          ?public?void?updateProductStockCountById(Integer?stockCount,?Long?id){
          ??productDao.updateProductStockCountById(stockCount,?id);
          ?}
          }

          submitOrder()方法和updateProductStockCountById()方法都在OrderService類(lèi)中,submitOrder()方法上沒(méi)有標(biāo)注事務(wù)注解,updateProductStockCountById()方法上標(biāo)注了事務(wù)注解,submitOrder()方法調(diào)用了updateProductStockCountById()方法,此時(shí),updateProductStockCountById()方法的事務(wù)在Spring中會(huì)失效。

          5.未配置事務(wù)管理器

          如果在項(xiàng)目中沒(méi)有配置Spring的事務(wù)管理器,即使使用了Spring的事務(wù)管理功能,Spring的事務(wù)也不會(huì)生效。

          例如,沒(méi)有在項(xiàng)目的配置類(lèi)中配置如下代碼。

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

          此時(shí),Spring的事務(wù)就會(huì)失效。

          6.方法的事務(wù)傳播類(lèi)型不支持事務(wù)

          如果內(nèi)部方法的事務(wù)傳播類(lèi)型為不支持事務(wù)的傳播類(lèi)型,則內(nèi)部方法的事務(wù)在Spring中會(huì)失效。

          例如,如下代碼所示。

          @Service
          public?class?OrderService?{
          ?@Autowired
          ?private?OrderDao?orderDao;
          ?@Autowired
          ?private?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);
          ??//減庫(kù)存
          ??this.updateProductStockCountById(1,?1L);
          ?}

          ?@Transactional(propagation?=?Propagation.NOT_SUPPORTED)
          ?public?void?updateProductStockCountById(Integer?stockCount,?Long?id){
          ??productDao.updateProductStockCountById(stockCount,?id);
          ?}
          }

          由于updateProductStockCountById()方法的事務(wù)傳播類(lèi)型為NOT_SUPPORTED,不支持事務(wù),則updateProductStockCountById()方法的事務(wù)會(huì)在Spring中失效。

          7.不正確的捕獲異常

          不正確的捕獲異常也會(huì)導(dǎo)致Spring的事務(wù)失效,示例如下。

          @Service
          public?class?OrderService?{
          ?@Autowired
          ?private?OrderDao?orderDao;
          ?@Autowired
          ?private?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);
          ??//減庫(kù)存
          ??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("扣減庫(kù)存異常:",?e.getMesaage());
          ??}
          ?}
          }

          updateProductStockCountById()方法中使用try-catch代碼塊捕獲了異常,即使updateProductStockCountById()方法內(nèi)部會(huì)拋出異常,但也會(huì)被catch代碼塊捕獲到,此時(shí)updateProductStockCountById()方法的事務(wù)會(huì)提交而不會(huì)回滾,并且submitOrder()方法的事務(wù)會(huì)提交而不會(huì)回滾,這就造成了Spring事務(wù)的回滾失效問(wèn)題。

          8.錯(cuò)誤的標(biāo)注異常類(lèi)型

          如果在@Transactional注解中標(biāo)注了錯(cuò)誤的異常類(lèi)型,則Spring事務(wù)的回滾會(huì)失效,示例如下。

          @Transactional(propagation?=?Propagation.REQUIRED)
          public?void?updateProductStockCountById(Integer?stockCount,?Long?id){
          ?try{
          ??productDao.updateProductStockCountById(stockCount,?id);
          ?}catch(Exception?e){
          ??logger.error("扣減庫(kù)存異常:",?e.getMesaage());
          ??throw?new?Exception("扣減庫(kù)存異常");
          ?}
          }

          在updateProductStockCountById()方法中捕獲了異常,并且在異常中拋出了Exception類(lèi)型的異常,此時(shí),updateProductStockCountById()方法事務(wù)的回滾會(huì)失效。

          為何會(huì)失效呢?這是因?yàn)镾pring中對(duì)于默認(rèn)回滾的事務(wù)異常類(lèi)型為RuntimeException,上述代碼拋出的是Exception異常。

          默認(rèn)情況下,Spring事務(wù)中無(wú)法捕獲到Exception異常,所以此時(shí)updateProductStockCountById()方法事務(wù)的回滾會(huì)失效。

          此時(shí)可以手動(dòng)指定updateProductStockCountById()方法標(biāo)注的事務(wù)異常類(lèi)型,如下所示。

          @Transactional(propagation?=?Propagation.REQUIRED,rollbackFor?=?Exception.class)

          這里,需要注意的是:Spring事務(wù)注解@Transactional中的rollbackFor屬性可以指定 Throwable 異常類(lèi)及其子類(lèi)。

          好了,今天就到這兒吧,我們下期見(jiàn)~~

          瀏覽 71
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  日本www色 | 干欧美视频 | 99这里只有精品热 | 美女被操短视频 | 亚洲福利一区 |