偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

Spring事務(wù)傳播屬性有那么難嗎?看這一篇就夠了

數(shù)據(jù)庫 其他數(shù)據(jù)庫
學(xué)習(xí)東西要知行合一,如果只是知道理論而沒實(shí)踐過,那么掌握的也不會特別扎實(shí),估計過幾天就會忘記,接下來我們一起實(shí)踐來學(xué)習(xí)Spring事務(wù)的傳播屬性。

[[280278]]

筆者文筆功力尚淺,如有不妥,請慷慨指出,必定感激不盡

 學(xué)習(xí)東西要知行合一,如果只是知道理論而沒實(shí)踐過,那么掌握的也不會特別扎實(shí),估計過幾天就會忘記,接下來我們一起實(shí)踐來學(xué)習(xí)Spring事務(wù)的傳播屬性。

傳播屬性

傳播屬性定義的是當(dāng)一個事務(wù)方法碰到另一個事務(wù)方法時的處理行為,一共有七種行為,定義如下

傳播性 描述
PROPAGATION_REQUIRED 0 支持當(dāng)前事務(wù),如果沒有就新建事務(wù)
PROPAGATION_SUPPORTS 1 支持當(dāng)前事務(wù),如果沒有就不以事務(wù)的方式運(yùn)行
PROPAGATION_MANDATORY 2 支持當(dāng)前事務(wù),如果當(dāng)前沒事務(wù)就拋異常
PROPAGATION_REQUIRES_NEW 3 無論當(dāng)前是否有事務(wù),都會新起一個事務(wù)
PROPAGATION_NOT_SUPPORTED 4 不支持事務(wù),如果當(dāng)前存在事務(wù),就將此事務(wù)掛起不以事務(wù)方式運(yùn)行
PROPAGATION_NEVER 5 不支持事務(wù),如果有事務(wù)就拋異常
PROPAGATION_NESTED 6 如果當(dāng)前存在事務(wù),在當(dāng)前事務(wù)中再新起一個事務(wù)

其實(shí)只看概念的話已經(jīng)很直截了當(dāng)了說明了每個傳播性的作用,此時我們再用具體的例子演示一下每個傳播性屬性下的行為。

此次演示我們使用的是H2數(shù)據(jù)庫,這個數(shù)據(jù)庫是作用在內(nèi)存里面的,所以對于我們演示事務(wù)效果來說正好,無需我們在進(jìn)行其他的配置了,我們新建一個表。將下面語句放在schema.sql文件里面即可,SpringBoot程序在啟動的時候就會自動為我們在內(nèi)存里面建立這樣的一個表。 

  1. CREATE TABLE FOO (ID INT IDENTITY, BAR VARCHAR(64)); 

演示之前我們會定義兩個類FooService和BarService。我們使用BarService 里面的方法進(jìn)行調(diào)用FooService 中的方法。

環(huán)境準(zhǔn)備

在進(jìn)行事務(wù)演示之前,其實(shí)可以分為以下幾種情況,根據(jù)排列組合,我們可以得出以下八種情況

  •  調(diào)用者:有無事務(wù)
  •  調(diào)用者:是否有異常
  •  被調(diào)用者:有無事務(wù)**(這個是通過傳播屬性進(jìn)行控制的)**所以并不在排列組合中
  •  被調(diào)用者:是否有異常
調(diào)用者是否有事務(wù) 調(diào)用者是否有異常 被調(diào)用者是否有異常

異常類

其中的RollbackException是我們自己定義的一個異常類 

  1. @Service  
  2. public class BarServiceImpl implements BarService{  
  3.     @Autowired  
  4.     private FooService fooService; 
  5.     // PROPAGATION_REQUIRED演示 無事務(wù)  
  6.     @Override  
  7.     public void testRequiredNoTransactional() throws RollbackException {  
  8.         fooService.testRequiredTransactional();  
  9.     }  

調(diào)用者

在BarService中定義兩個方法,一個是帶著事務(wù)的,一個是不帶事務(wù)的 

  1. // 有事務(wù)  
  2. @Override  
  3. @Transactional(rollbackFor = Exception.class)  
  4. public void hasTransactional() throws RollbackException {  
  5.  
  6. // 無事務(wù)  
  7. @Override  
  8. public void noTransactional() throws RollbackException {  

接下來我們就根據(jù)俄上面定義的八種情況進(jìn)行事務(wù)傳播屬性的學(xué)習(xí)。

PROPAGATION_REQUIRED

在此傳播屬性下,被調(diào)用方是否新建事務(wù)取決去調(diào)用者是否帶著事務(wù)。

想要了解這個傳播屬性的特性,其實(shí)我們演示上面八種情況的兩個例子就夠了

調(diào)用者是否有事務(wù) 調(diào)用者是否有異常 被調(diào)用者是否有異常
  •  第一種情況我們在被調(diào)用者拋出異常的情況下,如果查詢不到插入的數(shù)據(jù),那么就說明被調(diào)用者在調(diào)用者沒有事務(wù)的情況下自己新建了事務(wù)。
  •  第二種情況我們在調(diào)用者拋出異常的情況下,如果查詢不到插入的數(shù)據(jù),那么就說明被調(diào)用者在調(diào)用者有事務(wù)的情況下就加入當(dāng)前事務(wù)了。

我們先來看一下被調(diào)用者的類的方法例子。 

  1. @Service  
  2. public class FooServiceImpl implements FooService {  
  3.     @Autowired  
  4.     private JdbcTemplate jdbcTemplate;    
  5.     // REQUIRED傳播屬性-被調(diào)用者有異常拋出  
  6.     @Override  
  7.     @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)  
  8.     public void testRequiredHasException() throws RollbackException {  
  9.         jdbcTemplate.execute("INSERT INTO FOO (BAR) VALUES ("+Global.REQUIRED_HAS_EXCEPTION+")");  
  10.         throw new RollbackException();  
  11.     }  
  12.     // REQUIRED傳播屬性-被調(diào)用者無異常拋出  
  13.     @Override  
  14.     @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)  
  15.     public void testRequiredNoException() throws RollbackException {  
  16.         jdbcTemplate.execute("INSERT INTO FOO (BAR) VALUES ("+Global.REQUIRED_NO_EXCEPTION+")");  
  17.     }  

接下來我們看一下調(diào)用者方法的例子 

  1. @Service  
  2. public class BarServiceImpl implements BarService{  
  3.     @Autowired  
  4.     private FooService fooService;  
  5.     // 有事務(wù)  
  6.     @Override  
  7.     @Transactional(rollbackFor = Exception.class)  
  8.     public void hasTransactional() throws RollbackException {  
  9.         // 調(diào)用者有事務(wù),拋異常  被調(diào)用者無異常  
  10.         fooService.testRequiredNoException();  
  11.         throw new RollbackException();  
  12.     }  
  13.     // 無事務(wù)  
  14.     @Override  
  15.     public void noTransactional() throws RollbackException {  
  16.         // 調(diào)用者無事務(wù),不拋異常  被調(diào)用者有異常  
  17.         fooService.testRequiredHasException();  
  18.     }  

此時我們在程序調(diào)用時進(jìn)行查詢 

  1. String noException = Global.REQUIRED_NO_EXCEPTION;  
  2. String hasException = Global.REQUIRED_HAS_EXCEPTION;   
  3. try {  
  4.     barService.noTransactional();  
  5. }catch (Exception e){  
  6.     log.info("第一種情況 {}",  
  7.             jdbcTemplate  
  8.                     .queryForObject("SELECT COUNT(*) FROM FOO WHERE BAR='"+hasException+"'", Long.class));  
  9.  
  10. try {  
  11.     barService.hasTransactional();  
  12. }catch (Exception e){  
  13.     log.info("第二種情況 {}",  
  14.             jdbcTemplate  
  15.                     .queryForObject("SELECT COUNT(*) FROM FOO WHERE BAR='"+noException+"'", Long.class));  

查看打印出來的日志 

  1. 2019-10-16 13:02:04.142  INFO 11869 --- [           main] c.e.t.t.TransactionApplication           : 第一種情況 0  
  2. 2019-10-16 13:02:04.143  INFO 11869 --- [           main] c.e.t.t.TransactionApplication           : 第二種情況 0 

我們看到我們都沒有查到相應(yīng)的數(shù)據(jù),說明數(shù)據(jù)都回滾了。此時我們應(yīng)該就理解了那句話支持當(dāng)前事務(wù),如果沒有就新建事務(wù)。

PROPAGATION_SUPPORTS

被調(diào)用者是否有事務(wù),完全依賴于調(diào)用者,調(diào)用者有事務(wù)則有事務(wù),調(diào)用者沒事務(wù)則沒事務(wù)。

接下來我們還是用上面的兩個例子進(jìn)行演示

調(diào)用者是否有事務(wù) 調(diào)用者是否有異常 被調(diào)用者是否有異常
  •  第一種情況:被調(diào)用者拋出異常的情況下,如果仍能查詢到數(shù)據(jù),說明事務(wù)沒有回滾,說明被調(diào)用者沒有事務(wù)
  •  第二種情況:調(diào)用者拋出異常情況下,如果查不到數(shù)據(jù),說明兩個方法在一個事務(wù)中

接下來仍然是例子演示

被調(diào)用者,只是將@Transactional 注解中的propagation 屬性更換為了Propagation.SUPPORTS 

  1. // SUPPORTS傳播屬性-被調(diào)用者有異常拋出  
  2. @Override  
  3. @Transactional(rollbackFor = Exception.class,propagation = Propagation.SUPPORTS)  
  4. public void testSupportsHasException() throws RollbackException {  
  5.     jdbcTemplate.execute("INSERT INTO FOO (BAR) VALUES ('"+Global.SUPPORTS_HAS_EXCEPTION+"')");  
  6.     throw new RollbackException();  
  7.  
  8. // SUPPORTS傳播屬性-被調(diào)用者無異常拋出  
  9. @Override  
  10. @Transactional(rollbackFor = Exception.class,propagation = Propagation.SUPPORTS)  
  11. public void testSupportsNoException() throws RollbackException {  
  12.     jdbcTemplate.execute("INSERT INTO FOO (BAR) VALUES ('"+Global.SUPPORTS_NO_EXCEPTION+"')");  

調(diào)用者和上面的例子調(diào)用一樣,我們直接查看執(zhí)行效果 

  1. 2019-10-16 13:50:27.738  INFO 12174 --- [           main] c.e.t.t.TransactionApplication           : 第一種情況 1  
  2. 2019-10-16 13:50:27.741  INFO 12174 --- [           main] c.e.t.t.TransactionApplication           : 第二種情況 0 

我們看到了在第一種情況下查到了數(shù)據(jù),說明在第一種情況下被調(diào)用者是沒有事務(wù)的。此時我們應(yīng)該就理解了這句話 支持當(dāng)前事務(wù),如果沒有就不以事務(wù)的方式運(yùn)行。

PROPAGATION_MANDATORY

依然是這兩個例子進(jìn)行演示

調(diào)用者是否有事務(wù) 調(diào)用者是否有異常 被調(diào)用者是否有異常
  •  第一種情況:因?yàn)檎{(diào)用者沒有事務(wù),所以此傳播屬性下應(yīng)該是拋異常的
  •  第二種情況:被調(diào)用者的事務(wù)和調(diào)用者事務(wù)是同樣的

接下來是被調(diào)用者的代碼例子 

  1. // MANDATORY傳播屬性-被調(diào)用者有異常拋出  
  2. @Override  
  3. @Transactional(rollbackFor = Exception.class,propagation = Propagation.MANDATORY)  
  4. public void testMandatoryHasException() throws RollbackException {  
  5.     jdbcTemplate.execute("INSERT INTO FOO (BAR) VALUES ('"+Global.SUPPORTS_HAS_EXCEPTION+"')");  
  6.     throw new RollbackException();  
  7.  
  8. // MANDATORY傳播屬性-被調(diào)用者無異常拋出  
  9. @Override  
  10. @Transactional(rollbackFor = Exception.class,propagation = Propagation.MANDATORY)  
  11. public void testMandatoryNoException() throws RollbackException {  
  12.     jdbcTemplate.execute("INSERT INTO FOO (BAR) VALUES ('"+Global.SUPPORTS_NO_EXCEPTION+"')");  

調(diào)用者和上面的例子調(diào)用一樣,我們直接查看執(zhí)行效果 

  1. 2019-10-16 13:58:39.178 ERROR 12317 --- [           main] c.e.t.t.TransactionApplication           : org.springframework.transaction.IllegalTransactionStateException: No existing transaction found for transaction marked with propagation 'mandatory' 
  2. 2019-10-16 13:58:39.276  INFO 12317 --- [           main] c.e.t.t.TransactionApplication           : 第一種情況 0 
  3. 2019-10-16 13:58:39.281  INFO 12317 --- [           main] c.e.t.t.TransactionApplication           : 第二種情況 0 

我們發(fā)現(xiàn)和我們推測一樣,說明被調(diào)用者是不會自己新建事務(wù)的,此時我們應(yīng)該就理解了這句話支持當(dāng)前事務(wù),如果當(dāng)前沒事務(wù)就拋異常。

PROPAGATION_REQUIRES_NEW

此傳播屬性下,無論調(diào)用者是否有事務(wù),被調(diào)用者都會新建一個事務(wù)

調(diào)用者是否有事務(wù) 調(diào)用者是否有異常 被調(diào)用者是否有異常
  •  第一種情況:調(diào)用者無事務(wù),被調(diào)用者會新建事務(wù),所以查不到數(shù)據(jù)
  •  第二種情況:調(diào)用者有事務(wù),被調(diào)用者會新建一個事務(wù),所以調(diào)用者拋異常影響不到被調(diào)用者,所以能查到數(shù)據(jù)

接下來我們演示代碼。

被調(diào)用者 

  1. // REQUIRES_NEW傳播屬性-被調(diào)用者有異常拋出  
  2. @Override  
  3. @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRES_NEW)  
  4. public void testRequiresNewHasException() throws RollbackException {  
  5.     jdbcTemplate.execute("INSERT INTO FOO (BAR) VALUES ('"+Global.REQUIRES_NEW_HAS_EXCEPTION+"')");  
  6.     throw new RollbackException(); 
  7.  
  8. // REQUIRES_NEW傳播屬性-被調(diào)用者無異常拋出  
  9. @Override  
  10. @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRES_NEW)  
  11. public void testRequiresNewNoException() throws RollbackException {  
  12.     jdbcTemplate.execute("INSERT INTO FOO (BAR) VALUES ('"+Global.REQUIRES_NEW_NO_EXCEPTION+"')");  

調(diào)用者的例子和上面的相同,我們直接來看執(zhí)行情況 

  1. 2019-10-16 16:29:20.296  INFO 15553 --- [           main] c.e.t.t.TransactionApplication           : 第一種情況 0  
  2. 2019-10-16 16:29:20.298  INFO 15553 --- [           main] c.e.t.t.TransactionApplication           : 第二種情況 1 

我們發(fā)現(xiàn)和我們的推論是一樣的,說明調(diào)用者的事務(wù)和被調(diào)用者的事務(wù)完全無關(guān)。此時我們應(yīng)該就理解這句話了無論當(dāng)前是否有事務(wù),都會新起一個事務(wù)。

PROPAGATION_NOT_SUPPORTED

無論調(diào)用者是否有事務(wù),被調(diào)用者都不以事務(wù)的方法運(yùn)行

同樣是這兩個例子

調(diào)用者是否有事務(wù) 調(diào)用者是否有異常 被調(diào)用者是否有異常
  •  第一種情況:被調(diào)用者都不會有事務(wù),那么在拋異常之后就能查到相應(yīng)的數(shù)據(jù)
  •  第二種情況:在調(diào)用者有事務(wù)的情況下,被調(diào)用者也會在無事務(wù)環(huán)境下運(yùn)行,所以我們依然能查到數(shù)據(jù)

接下來驗(yàn)證我們的猜測 

  1. // NOT_SUPPORTED傳播屬性-被調(diào)用者有異常拋出  
  2. @Override  
  3. @Transactional(rollbackFor = Exception.class,propagation = Propagation.NOT_SUPPORTED) 
  4. public void testNotSupportHasException() throws RollbackException {  
  5.     jdbcTemplate.execute("INSERT INTO FOO (BAR) VALUES ('"+Global.NOT_SUPPORTS_HAS_EXCEPTION+"')");  
  6.     throw new RollbackException();  
  7.  
  8. // NOT_SUPPORTED傳播屬性-被調(diào)用者無異常拋出  
  9. @Override  
  10. @Transactional(rollbackFor = Exception.class,propagation = Propagation.NOT_SUPPORTED)  
  11. public void testNotSupportNoException() throws RollbackException {  
  12.     jdbcTemplate.execute("INSERT INTO FOO (BAR) VALUES ('"+Global.NOT_SUPPORTS_NO_EXCEPTION+"')");  

然后查看執(zhí)行結(jié)果 

  1. 2019-10-16 16:38:35.065  INFO 15739 --- [           main] c.e.t.t.TransactionApplication           : 第一種情況 1  
  2. 2019-10-16 16:38:35.067  INFO 15739 --- [           main] c.e.t.t.TransactionApplication           : 第二種情況 1 

我們可以看到在最后兩種情況都查到了數(shù)據(jù),根據(jù)演示效果應(yīng)該可以理解這句話了,不支持事務(wù),如果當(dāng)前存在事務(wù),就將此事務(wù)掛起不以事務(wù)方式運(yùn)行。

PROPAGATION_NEVER

調(diào)用者有事務(wù),被調(diào)用者就會拋出異常

調(diào)用者是否有事務(wù) 調(diào)用者是否有異常 被調(diào)用者是否有異常

這個就不演示,相信大家看到這里應(yīng)該都會明白在第一種情況下我們是能夠查到數(shù)據(jù)的。在第二種情況下由于調(diào)用者帶著事務(wù),所以會拋異常。

PROPAGATION_NESTED

此傳播屬性下,被調(diào)用者的事務(wù)是調(diào)用者的事務(wù)的子集。

我們重點(diǎn)說一下NESTED的傳播屬性的特性

調(diào)用者是否有事務(wù) 說明
被調(diào)用者會新起一個事務(wù),此事務(wù)和調(diào)用者事務(wù)是一個嵌套的關(guān)系
被調(diào)用者會自己新起一個事務(wù)

關(guān)于什么是嵌套事務(wù)的關(guān)系,我們用下面三個例子能夠進(jìn)行演示。

調(diào)用者是否有事務(wù) 調(diào)用者是否有異常 被調(diào)用者是否有異常
  •  第一種情況:如果查不到數(shù)據(jù),則說明在調(diào)用者無事務(wù)情況下,被調(diào)用者會新起一個事務(wù)
  •  第二種情況:如果查不到數(shù)據(jù),說明外層事務(wù)能夠影響內(nèi)層事務(wù)
  •  第三種情況:如果查到數(shù)據(jù),說明內(nèi)層事務(wù)不影響外層事務(wù)

接下來我們編寫具體的代碼 

  1. // NESTED傳播屬性-回滾事務(wù)  
  2. @Override  
  3. @Transactional(rollbackFor = Exception.class,propagation = Propagation.NESTED)  
  4. public void testNestedHasException() throws RollbackException {  
  5.     jdbcTemplate.execute("INSERT INTO FOO (BAR) VALUES ('"+Global.NESTED_HAS_EXCEPTION+"')");  
  6.    // TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();  
  7.     throw new RollbackException();  
  8.  
  9. // NESTED傳播屬性-不回滾事務(wù)  
  10. @Override  
  11. @Transactional(rollbackFor = Exception.class,propagation = Propagation.NESTED)  
  12. public void testNestedNoException() throws RollbackException {  
  13.     jdbcTemplate.execute("INSERT INTO FOO (BAR) VALUES ('"+Global.NESTED_NO_EXCEPTION+"')");  

然后接下來的調(diào)用者也會有點(diǎn)區(qū)別 

  1. @Override  
  2. @Transactional()  
  3. public void hasTransactionalNoException() throws RollbackException {  
  4.     // NESTED傳播屬性 - 調(diào)用者有事務(wù),不拋異常  被調(diào)用者有異常  
  5.     jdbcTemplate.execute("INSERT INTO FOO (BAR) VALUES ('"+Global.NESTED_HAS_EXCEPTION_TWO+"')");  
  6.     fooService.testNestedHasException();  

然后執(zhí)行效果 

  1. 2019-10-16 18:01:06.387  INFO 17172 --- [           main] c.e.t.t.TransactionApplication           : 第一種情況 0  
  2. 2019-10-16 18:01:06.389  INFO 17172 --- [           main] c.e.t.t.TransactionApplication           : 第二種情況 0  
  3. 2019-10-16 18:01:06.390  INFO 17172 --- [           main] c.e.t.t.TransactionApplication           : 第三種情況 1 

可以看出來嵌套事務(wù)的本質(zhì)就是外層會影響內(nèi)層,內(nèi)層不影響外層。而REQUIRES_NEW則是互不影響。

總結(jié)

到現(xiàn)在我們已經(jīng)全部分析完了七種傳播屬性,從寫這篇文章開始到結(jié)束其中也碰到過一些坑,有些是不自己實(shí)踐一遍是根本不知道的,所以我還是建議讀者看完這篇文章以后自己進(jìn)行實(shí)踐,演示各種情況,只有這樣才能夠爛熟于心。 

 

責(zé)任編輯:龐桂玉 來源: 中國開源
相關(guān)推薦

2022-08-01 11:33:09

用戶分析標(biāo)簽策略

2023-09-11 08:13:03

分布式跟蹤工具

2021-04-08 07:37:39

隊(duì)列數(shù)據(jù)結(jié)構(gòu)算法

2020-02-18 16:20:03

Redis ANSI C語言日志型

2023-02-10 09:04:27

2022-06-20 09:01:23

Git插件項(xiàng)目

2017-03-11 22:19:09

深度學(xué)習(xí)

2023-11-18 09:30:42

模型AI

2022-04-07 10:39:21

反射Java安全

2020-07-03 08:21:57

Java集合框架

2019-05-14 09:31:16

架構(gòu)整潔軟件編程范式

2023-10-17 08:15:28

API前后端分離

2018-05-22 08:24:50

PythonPyMongoMongoDB

2024-09-23 08:00:00

消息隊(duì)列MQ分布式系統(tǒng)

2019-04-02 10:51:29

瀏覽器緩存前端

2017-03-13 09:50:46

Python裝飾器

2019-12-31 09:56:16

Linux 系統(tǒng) 數(shù)據(jù)

2019-09-05 08:14:44

Puppet部署結(jié)構(gòu)

2020-07-06 08:06:00

Java模塊系統(tǒng)

2019-04-10 10:43:15

Redis內(nèi)存淘汰策略
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號