欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Spring七大事務(wù)傳遞機(jī)制深入分析實(shí)現(xiàn)原理

 更新時(shí)間:2023年03月27日 09:07:50   作者:一路向陽向北  
實(shí)際項(xiàng)目開發(fā)中,如果涉及到多張表操作時(shí),為了保證業(yè)務(wù)數(shù)據(jù)的一致性,大家一般都會(huì)采用事務(wù)機(jī)制,好多小伙伴可能只是簡(jiǎn)單了解一下,遇到事務(wù)失效的情況,便會(huì)無從下手,下面這篇文章主要給大家介紹了關(guān)于Spring事務(wù)傳遞機(jī)制的相關(guān)資料,需要的朋友可以參考下

Spring事務(wù)傳遞機(jī)制原理

首先,我們通過org.springframework.transaction.annotation.Propagation來了解一下spring事務(wù)的傳播定義:

1. REQUIRED(默認(rèn)):

Support a current transaction, create a new one if none exists.

支持當(dāng)前事務(wù),如果沒有則創(chuàng)建一個(gè)新的

2. SUPPORTS

Support a current transaction, execute non-transactionally if none exists.

支持當(dāng)前事務(wù),如果沒有則不使用事務(wù)

3. MANDATORY

Support a current transaction, throw an exception if none exists

支持當(dāng)前事務(wù),如果沒有事務(wù)則報(bào)錯(cuò)

4. REQUIRED_NEW

Create a new transaction, and suspend the current transaction if one exists.

新建一個(gè)事務(wù),同時(shí)將當(dāng)前事務(wù)掛起

5. NOT_SUPPORTED

Execute non-transactionally, suspend the current transaction if one exists

以無事務(wù)的方式執(zhí)行,如果當(dāng)前有事務(wù)則將其掛起

6. NEVER

Execute non-transactionally, throw an exception if a transaction exists.

以無事務(wù)的方式執(zhí)行,如果當(dāng)前有事務(wù)則報(bào)錯(cuò)

7. NESTED

Execute within a nested transaction if a current transaction exists,behave like PROPAGATION_REQUIRED else

如果當(dāng)前有事務(wù),則在當(dāng)前事務(wù)內(nèi)部嵌套一個(gè)事務(wù),內(nèi)部事務(wù)的回滾不影響當(dāng)前事務(wù)。如果當(dāng)前沒有事務(wù),就相當(dāng)于REQUIRED

Note: Actual creation of a nested transaction will only work on specific transaction managers. Out of the box, this only applies to

the JDBC DataSourceTransactionManager when working on a JDBC 3.0 driver.

Some JTA providers might support nested transactions as well.

注意:該定義只能在JDBC3.0驅(qū)動(dòng)下的DataSourceTransactionManager事務(wù)管理器中使用,有些JTA事務(wù)可能也會(huì)支持

接下來我們通過代碼驗(yàn)證一下spring事務(wù)的傳遞性,在UserServiceImpl類添加兩個(gè)方法如下:

@Transactional(propagation = Propagation.NEVER)
public User findById(Long id) {
    User user =  userMapper.findById(id);
    System.out.println("find user:"+user);
    return user;
}
@Transactional
public void transactionTest(int t) {
    findById(t+0L);
}

我們調(diào)用transactionTest方法,transactionTest沒有配置Propagation,所以默認(rèn)是REQUIRED,會(huì)在當(dāng)前新建一個(gè)事務(wù)。transactionTest內(nèi)部調(diào)用findById,由于findById事務(wù)傳播定義為NEVER,表明它當(dāng)前不能有事務(wù),按理說這里會(huì)拋出異常,但是我們利用junit執(zhí)行后發(fā)現(xiàn),transactionTest是可以正常執(zhí)行的。

事實(shí)上,如果使用@Transaction方法里嵌套調(diào)用的是同一個(gè)類的方法,spring代理會(huì)忽略嵌套方法的@Transaction配置。但是,如果是其他注入對(duì)象的方法,那么@Transaction配置就會(huì)生效。我們將上面的transactionTest方法的事務(wù)傳播定義為NERVER,并新增一個(gè)insert操作,即使insert啟用了事務(wù)并且拋出異常,但是事務(wù)不會(huì)生效,也不會(huì)有回滾的說法,程序會(huì)拋出異常但是數(shù)據(jù)會(huì)保存到數(shù)據(jù)庫中:

@Transactional(propagation = Propagation.NEVER)
public void transactionTest(int t) {
    findById(t+0L);
    insertUser("huangxl","abc123");
}
@Transactional
public int insertUser(String name, String password) {
    User user = new User();
    user.setPassword(password);
    user.setUsername(name);
    int insertCount =  userMapper.insertEntity(user);
    if(insertCount == 1 ){
        throw new RuntimeException("test transaction roll back");
    }
    return insertCount;
}

接下來我們來測(cè)試不同類之間的方法(事務(wù))調(diào)用,以下的測(cè)試都是基于junit執(zhí)行TransactionTestServiceImpl.test()方法

一、Propagation.NERVER的測(cè)試

下面我們將UserService注入到TransactionTestServiceImpl中,test方法使用@Transactional,UserService findById事務(wù)傳播定義不變,還是NERVER。

UserserviceImpl:
@Service
public class TransactionTestServiceImpl implements TransactionTestService {
    @Autowired
    private UserService userService;
    @Override
    @Transactional
    public void test() {
        userService.findById(1L);
    }
}
TransactionTestServiceImpl:
@Service
public class UserServiceImpl implements UserService {
    @Override
    @Transactional(propagation = Propagation.NEVER)
    public User findById(Long id) {
        User user =  userMapper.findById(id);
        System.out.println("find user:"+user);
        return user;
    }
}

由于test默認(rèn)啟用了事務(wù),findById不允許當(dāng)前有事務(wù),所以我們執(zhí)行test方法后會(huì)發(fā)現(xiàn)程序拋出了異常:

org.springframework.transaction.IllegalTransactionStateException: Existing transaction found for transaction marked with propagation ‘never’

結(jié)論:

NERVER 不允許當(dāng)前存在事務(wù)

二、Propagation.REQUIRED的測(cè)試

UserserviceImpl:
@Transactional
public int insertUser(String name, String password) {
    User user = new User();
    user.setPassword(password);
    user.setUsername(name);
    int insertCount =  userMapper.insertEntity(user);
    if(insertCount == 1 ){
        throw new RuntimeException("test transaction roll back");
    }
    return insertCount;
}
TransactionTestServiceImpl:
@Transactional
public void test() {
    try {
        userService.insertUser("abc", "123");
    } catch (Exception e) {
        //do Nothing
    }
    userMapper.updateUserPassWord(1L, "456");
}

我們會(huì)發(fā)現(xiàn),即使捕獲了userService.insertUser拋出的異常,test還是把insertUser和updateUserPassword操作當(dāng)成是一個(gè)整體,整個(gè)事務(wù)還是回滾了,程序拋出了下面的異常:

org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only

結(jié)論:

REQUIRED子事務(wù)會(huì)影響當(dāng)前事務(wù)的提交、回滾

三、Propagation.NESTED的測(cè)試

UserserviceImpl:
@Transactional(propagation = Propagation.NESTED)
public int insertUser(String name, String password) {
    User user = new User();
    user.setPassword(password);
    user.setUsername(name);
    int insertCount =  userMapper.insertEntity(user);
    if(insertCount == 1 ){
        throw new RuntimeException("test transaction roll back");
    }
    return insertCount;
}
TransactionTestServiceImpl:
@Transactional
public void test() {
    try {
        userService.insertUser("abc", "123");
    } catch (Exception e) {
        //do Nothing
    }
    userMapper.updateUserPassWord(1L, "456");
}

程序正常運(yùn)行,因?yàn)镹ESTED內(nèi)部事務(wù)回滾不影響外部事務(wù)。假如這個(gè)時(shí)候我們把test的@Transactional去掉再運(yùn)行test方法,發(fā)現(xiàn)insertUser沒有插入用戶信息,說明當(dāng)前沒有事務(wù)的情況下,NESTED會(huì)默認(rèn)創(chuàng)建一個(gè)事務(wù),類似于REQUIRED。

如果我們把程序改為下面的情況:

UserserviceImpl:
@Transactional(propagation = Propagation.NESTED)
public int insertUser(String name, String password) {
    User user = new User();
    user.setPassword(password);
    user.setUsername(name);
    int insertCount =  userMapper.insertEntity(user);
    return insertCount;
}
TransactionTestServiceImpl:
@Transactional
public void test() {
    userService.insertUser("abc", "123");
    int updateRow = userMapper.updateUserPassWord(1L, "456");
    if (updateRow == 1) {
        throw new RuntimeException("transational roll back");
    }
}

我們會(huì)發(fā)現(xiàn)沒有插入用戶信息,當(dāng)前事務(wù)和子事務(wù)全部回滾。

結(jié)論:

NESTED子事務(wù)回滾不會(huì)影響當(dāng)前事務(wù)的提交(catch回滾異常的情況下),但是當(dāng)前事務(wù)回滾會(huì)回滾子事務(wù)。也就是說只有當(dāng)前事務(wù)提交成功了,子事務(wù)才會(huì)提交成功。

四、Propagation.REQUIRED_NEW的測(cè)試

UserserviceImpl:
@Transactional(propagation = Propagation.REQUIRES_NEW)
public int insertUser(String name, String password) {
    User user = new User();
    user.setPassword(password);
    user.setUsername(name);
    int insertCount =  userMapper.insertEntity(user);
    return insertCount;
}
TransactionTestServiceImpl:
@Transactional
public void test() {
    userService.insertUser("abc", "123");
    int updateRow = userMapper.updateUserPassWord(1L, "456");
    if (updateRow == 1) {
        throw new RuntimeException("transational roll back");
    }
}

運(yùn)行結(jié)果:程序報(bào)錯(cuò),但是有用戶信息插入。

將程序改為下面的樣子:

UserserviceImpl:
@Transactional(propagation = Propagation.REQUIRES_NEW)
public int updateUserPassWorld(Long id, String password) {
    int update =  userMapper.updateUserPassWord(id,password);
    return update;
}
TransactionTestServiceImpl:
@Transactional
public void test() {
    //當(dāng)前事務(wù)
    userMapper.updateUserPassWord(28L, "123456");
    //執(zhí)行REQUIRES_NEW事務(wù)
    userService.updateUserPassWorld(28L, "000000");
   System.out.println("commit");
}

執(zhí)行程序,發(fā)現(xiàn)程序遲遲沒有打印字符串commit,發(fā)生了死鎖。

結(jié)論:

REQUIRES_NEW會(huì)啟用一個(gè)新的事務(wù),事務(wù)擁有完全獨(dú)立的能力,它不依賴于當(dāng)前事務(wù),執(zhí)行時(shí)會(huì)掛起當(dāng)前事務(wù),直到REQUIRES_NEW事務(wù)完成提交后才會(huì)提交當(dāng)前事務(wù),如果當(dāng)前事務(wù)與REQUIRES_NEW 存在鎖競(jìng)爭(zhēng),會(huì)導(dǎo)致死鎖。

五、NOT_SUPPORTED的測(cè)試

UserserviceImpl:
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public int updateUserPassWorld(Long id, String password) {
    int updateRow =  userMapper.updateUserPassWord(id,password);
if(updateRow ==1 ){
    throw new RuntimeException("roll back test");
}
return updateRow;
}
TransactionTestServiceImpl:
@Transactional
public void test() {
    userService.updateUserPassWorld(28L, "000000");
}

程序運(yùn)行報(bào)錯(cuò),但是id為28的用戶密碼還是更新了。

將程序改為下面這個(gè)情況:

UserserviceImpl:
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public int updateUserPassWorld(Long id, String password) {
    int update =  userMapper.updateUserPassWord(id,password);
    return update;
}
TransactionTestServiceImpl:
@Transactional
public void test() {
    //當(dāng)前事務(wù)
    userMapper.updateUserPassWord(28L, "123456");
    //執(zhí)行REQUIRES_NEW事務(wù)
    userService.updateUserPassWorld(28L, "000000");
   System.out.println("commit");
}

執(zhí)行程序,發(fā)現(xiàn)程序遲遲沒有打印字符串commit,發(fā)生了死鎖。

結(jié)論:

NOT_SUPPORTED會(huì)掛起當(dāng)前事務(wù),并且NOT_SUPPORTED定義的方法內(nèi)部不啟用顯示事務(wù),如果NOT_SUPPORTED和當(dāng)前事務(wù)存在鎖競(jìng)爭(zhēng),會(huì)發(fā)生死鎖。

六、NOT_SUPPORTED的測(cè)試

UserserviceImpl:
@Transactional(propagation = Propagation.MANDATORY)
public int updateUserPassWorld(Long id, String password) {
    int updateRow =  userMapper.updateUserPassWord(id,password);
    return updateRow;
}
TransactionTestServiceImpl:
public void test() {
    userService.updateUserPassWorld(28L, "123456");
}

程序運(yùn)行錯(cuò)誤:

org.springframework.transaction.IllegalTransactionStateException: No existing transaction found for transaction marked with propagation ‘mandatory’

結(jié)論:

MANDATORY必須包含在事務(wù)中,如果事務(wù)不存在,則拋出異常

到此這篇關(guān)于Spring七大事務(wù)傳遞機(jī)制深入分析實(shí)現(xiàn)原理的文章就介紹到這了,更多相關(guān)Spring事務(wù)傳遞機(jī)制內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Apache Commons fileUpload實(shí)現(xiàn)文件上傳之一

    Apache Commons fileUpload實(shí)現(xiàn)文件上傳之一

    這篇文章主要介紹了Apache Commons fileUpload實(shí)現(xiàn)文件上傳之一的相關(guān)資料,需要的朋友可以參考下
    2016-03-03
  • Java方法及數(shù)組相關(guān)原理解析

    Java方法及數(shù)組相關(guān)原理解析

    這篇文章主要介紹了Java方法及數(shù)組相關(guān)原理解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-12-12
  • Mybatis集成到Spring容器的詳細(xì)步驟

    Mybatis集成到Spring容器的詳細(xì)步驟

    在現(xiàn)在的JavaEE開發(fā)過程中,我們經(jīng)常會(huì)使用到Spring+SpringMVC+Mybatis這個(gè)組合,那么Mybatis是如何集成到Spring中的呢,下面通過實(shí)例代碼給大家詳細(xì)講解,感興趣的朋友跟隨小編一起看看吧
    2024-03-03
  • Spring中@Transactional注解的屬性說明

    Spring中@Transactional注解的屬性說明

    這篇文章主要介紹了Spring中@Transactional注解的屬性說明,@Transactional 是聲明式事務(wù)管理 編程中使用的注解,@Transactional 注解應(yīng)該只被應(yīng)用到 public 方法上,這是由 Spring AOP 的本質(zhì)決定的,需要的朋友可以參考下
    2023-11-11
  • 詳解Spring Cloud Alibaba Sidecar多語言微服務(wù)異構(gòu)

    詳解Spring Cloud Alibaba Sidecar多語言微服務(wù)異構(gòu)

    這篇文章主要介紹了詳解Spring Cloud Alibaba Sidecar多語言微服務(wù)異構(gòu),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-11-11
  • 詳解rabbitmq創(chuàng)建queue時(shí)arguments參數(shù)注釋

    詳解rabbitmq創(chuàng)建queue時(shí)arguments參數(shù)注釋

    這篇文章主要介紹了rabbitmq創(chuàng)建queue時(shí)arguments參數(shù)注釋,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-03-03
  • JavaWeb之Filter與Listener使用解析

    JavaWeb之Filter與Listener使用解析

    這篇文章主要介紹了JavaWeb之Filter與Listener使用解析,Filter表示過濾器,是JavaWeb三大組件(Servlet、Filter、Listener)之一,過濾器可以把對(duì)資源的請(qǐng)求攔截下來,從而實(shí)現(xiàn)一些特殊的功能,需要的朋友可以參考下
    2024-01-01
  • java中同類對(duì)象之間的compareTo()和compare()方法對(duì)比分析

    java中同類對(duì)象之間的compareTo()和compare()方法對(duì)比分析

    這篇文章主要介紹了java中同類對(duì)象之間的compareTo()和compare()方法對(duì)比分析,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-09-09
  • Scala異常處理的方法深入分析

    Scala異常處理的方法深入分析

    Scala是一種多范式的編程語言,支持面向?qū)ο蠛秃瘮?shù)式編程。Scala也支持異常處理,即在程序運(yùn)行過程中發(fā)生意外或錯(cuò)誤時(shí),采取相應(yīng)的措施
    2023-04-04
  • 詳解Java多線程與并發(fā)

    詳解Java多線程與并發(fā)

    多線程是一個(gè)進(jìn)程在執(zhí)行過程中產(chǎn)生多個(gè)更小的程序單元,這些更小的單元稱為線程,這些線程可以同時(shí)存在,同時(shí)運(yùn)行,一個(gè)進(jìn)程可能包含多個(gè)同時(shí)執(zhí)行的線程。多線程是實(shí)現(xiàn)并發(fā)機(jī)制的一種有效手段。進(jìn)程和線程一樣,都是實(shí)現(xiàn)并發(fā)的一個(gè)基本單位。
    2021-06-06

最新評(píng)論