Spring的事務(wù)傳播機(jī)制實(shí)例

1仅孩,Propagation.REQUIRED

如果當(dāng)前沒(méi)有事務(wù),就新建一個(gè)事務(wù)碧磅,如果已經(jīng)存在一個(gè)事務(wù)中碘箍,加入到這個(gè)事務(wù)中遵馆。詳細(xì)解釋在代碼下方。

看下代碼
員工service

@Service
public class EmployeeServiceImpl implements EmployeeService {

    @Autowired
    EmployeeMapper employeeMapper;

    @Autowired
    DepartmentService departmentService;

    /**
     * 添加員工的同時(shí)添加部門(mén)
     * REQUIRED 傳播
     * @param name 員工姓名
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public void addEmpByRequired(String name) {
        Employee employee = new Employee();
        employee.setDeptId(1);
        employee.setName(name);
        employee.setAddress("邯鄲");
        employeeMapper.insertSelective(employee);
        departmentService.addDept("jishubu");
        int i = 1/0;
    }
}

部門(mén)service

@Service
public class DepartmentServiceImpl implements DepartmentService {

    @Autowired
    DepartmentMapper departmentMapper;

    @Override
    public void addDeptByRequired(String name) {
        Department department = new Department();
        department.setName(name);
        departmentMapper.insertSelective(department);
//        int i = 1/0;
    }
}
注:該篇文章所測(cè)試的皆是運(yùn)行addEmpByRequired方法丰榴。

1货邓,上述代碼中,無(wú)論int i =1/0 這個(gè)異常出現(xiàn)在哪里四濒,添加員工和添加部門(mén)都會(huì)回滾换况。
因?yàn)?REQUIRED 會(huì)讓添加員工和添加部門(mén)變?yōu)橐粋€(gè)事務(wù)。,
2盗蟆,值得一提的是戈二,如果異常在addDept中,但是在addEmpByRequired把 addDept方法 try喳资,catch了觉吭,則會(huì)拋出異常:Transaction rolled back because it has been marked as rollback-only 。
3仆邓,如果在addDeptByRequired上添加@Transactional(propagation = Propagation.REQUIRED)鲜滩,在addEmpByRequired不添加事務(wù),則addDeptByRequired是一個(gè)事務(wù)节值,addEmpByRequired并不是一個(gè)事務(wù)绒北。因?yàn)閍ddDeptByRequired開(kāi)啟了一個(gè)事務(wù),但是addEmpByRequired并不存在一個(gè)事務(wù)中察署。

2,Propagation.SUPPORTS

支持當(dāng)前事務(wù)峻汉,如果當(dāng)前沒(méi)有事務(wù)贴汪,就以非事務(wù)方式執(zhí)行。

員工service

    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public void addEmpBySupports(String name) {
        Employee employee = new Employee();
        employee.setDeptId(2);
        employee.setName(name);
        employee.setAddress("邯鄲");
        employeeMapper.insertSelective(employee);
        departmentService.addDeptBySupports("jishubu");
//        int i = 1/0;
    }

部門(mén)Service

    @Override
    @Transactional(propagation = Propagation.SUPPORTS)
    public void addDeptBySupports(String name) {
        Department department = new Department();
        department.setName(name);
        departmentMapper.insertSelective(department);
        int i = 1/0;
    }

關(guān)于這個(gè)屬性休吠,在以上代碼中扳埂,主要是添加到addDeptBySupports上的,也就是被調(diào)用方法上瘤礁。因?yàn)樘砑拥絘ddEmpBySupports就不以事務(wù)的方式運(yùn)行了阳懂。
然后,如果addEmpBySupports為事務(wù)柜思,則addDeptBySupports也為事務(wù)岩调。如果addEmpBySupports不是事務(wù),則addDeptBySupports也不是事務(wù)赡盘。

3号枕,Propagation.MANDATORY

使用當(dāng)前的事務(wù),如果當(dāng)前沒(méi)有事務(wù)陨享,就拋出異常葱淳。

員工Service

    @Override
//    @Transactional(propagation = Propagation.REQUIRED)
    public void addEmpByMandatory(String name) {
        System.out.println("aaaaaa");
        Employee employee = new Employee();
        employee.setDeptId(3);
        employee.setName(name);
        employee.setAddress("邯鄲");
        employeeMapper.insertSelective(employee);
        departmentService.addDeptByMandatory("jishubu");
        int i = 1/0;
    }

部門(mén)Service

    @Override
    @Transactional(propagation = Propagation.MANDATORY)
    public void addDeptByMandatory(String name) {
        Department department = new Department();
        department.setName(name);
        departmentMapper.insertSelective(department);
        int i = 1/0;
    }

這個(gè)屬性也是添加到addDeptByMandatory(被調(diào)用者) 上的钝腺。如果添加到addEmpByMandatory(調(diào)用者)上,則直接拋出異常赞厕。
該屬性添加到addDeptByMandatory上艳狐, 如果addEmpByMandatory有事務(wù),則addDeptByMandatory加入到addEmpByMandatory的事務(wù)中皿桑,如果addEmpByMandatory沒(méi)有事務(wù)毫目,則直接拋出異常。

4唁毒,Propagation.REQUIRES_NEW

員工Service

    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void addEmpByRequiresNew(String name) {
        Employee employee = new Employee();
        employee.setDeptId(4);
        employee.setName(name);
        employee.setAddress("邯鄲");
        employeeMapper.insertSelective(employee);
        departmentService.addDeptByRequiresNew("jishubu");
        int i = 1/0;
    }

部門(mén)Service

    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void addDeptByRequiresNew(String name) {
        Department department = new Department();
        department.setName(name);
        departmentMapper.insertSelective(department);
//        int i = 1/0;
    }

這個(gè)屬性應(yīng)該是除了REQUIRED用的最多的蒜茴。這個(gè)屬性也是針對(duì)被調(diào)用者的(addDeptByRequiresNew)。
不管調(diào)用者(addEmpByRequiresNew)是否存在事務(wù)浆西,被調(diào)用者(addDeptByRequiresNew)都會(huì)新開(kāi)一個(gè)事務(wù)粉私,相當(dāng)于被調(diào)用者都存在于自己的事務(wù)中和調(diào)用者沒(méi)有關(guān)系。
如上述代碼近零,addEmpByRequiresNew會(huì)回滾诺核,但addDeptByRequiresNew不會(huì)回滾。因?yàn)樗麄兪莾蓚€(gè)事務(wù)久信。

5窖杀,Propagation.NOT_SUPPORTED

以非事務(wù)方式執(zhí)行操作,如果當(dāng)前存在事務(wù)裙士,就把當(dāng)前事務(wù)掛起入客。

員工Service

    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public void addEmpByNotSupported(String name) {
        Employee employee = new Employee();
        employee.setDeptId(5);
        employee.setName(name);
        employee.setAddress("邯鄲");
        employeeMapper.insertSelective(employee);
        departmentService.addDeptByNotSupported("jishubu");
        int i = 1/0;
    }

部門(mén)Service

    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public void addDeptByNotSupported(String name) {
        Department department = new Department();
        department.setName(name);
        departmentMapper.insertSelective(department);
        int i = 1/0;
    }

這個(gè)屬性如果放在調(diào)用者(addEmpByNotSupported)上,則是以非事務(wù)方式運(yùn)行腿椎。
如果放在被調(diào)用者(addDeptByNotSupported)上桌硫,該方法(addDeptByNotSupported)以非事務(wù)運(yùn)行,調(diào)用者如果有事務(wù)啃炸,則運(yùn)行單獨(dú)的事務(wù)(掛起)铆隘。
上述代碼,會(huì)出現(xiàn)添加員工回滾南用,添加部門(mén)不回滾膀钠。

6,Propagation.NEVER

以非事務(wù)方式執(zhí)行裹虫,如果當(dāng)前存在事務(wù)肿嘲,則拋出異常。

員工Service

    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public void addEmpByNever(String name) {
        Employee employee = new Employee();
        employee.setDeptId(6);
        employee.setName(name);
        employee.setAddress("邯鄲");
        employeeMapper.insertSelective(employee);
        departmentService.addDeptByNever("jishubu");
        int i = 1/0;
    }

部門(mén)Service

    @Override
    @Transactional(propagation = Propagation.NEVER)
    public void addDeptByNever(String name) {
        Department department = new Department();
        department.setName(name);
        departmentMapper.insertSelective(department);
        int i = 1/0;
    }

這個(gè)屬性如果在調(diào)用者上筑公,則直接以非事務(wù)運(yùn)行睦刃。如果作用在被調(diào)用者上,則看調(diào)用者是否有事務(wù)十酣,如果調(diào)用者有事務(wù)涩拙,則拋出異常际长,如果沒(méi)有事務(wù),則以非事務(wù)運(yùn)行兴泥。
上述代碼中工育,則會(huì)拋出異常。(并不是除0異常搓彻,而是:Existing transaction found for transaction marked with propagation 'never')

7如绸,Propagation.NESTED

如果當(dāng)前存在事務(wù),則在嵌套事務(wù)內(nèi)執(zhí)行旭贬。如果當(dāng)前沒(méi)有事務(wù)怔接,則執(zhí)行與PROPAGATION_REQUIRED類(lèi)似的操作。
(這個(gè)和REQUIRED區(qū)別在于一個(gè)是加入到一個(gè)事務(wù)稀轨,一個(gè)是在嵌套事務(wù)運(yùn)行)

員工Service

    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public void addEmpByNested(String name) {
        Employee employee = new Employee();
        employee.setDeptId(7);
        employee.setName(name);
        employee.setAddress("邯鄲");
        employeeMapper.insertSelective(employee);
        try {

            departmentService.addDeptByNested("jishubu");
        }catch (Exception e){

        }
//        int i = 1/0;
    }

部門(mén)Service

    @Override
    @Transactional(propagation = Propagation.NESTED)
    public void addDeptByNested(String name) {
        Department department = new Department();
        department.setName(name);
        departmentMapper.insertSelective(department);
        int i = 1/0;
    }

可以這么理解扼脐,大多數(shù)情況下,效果和REQUIRED一樣奋刽。但是有一種情況瓦侮,就是上述代碼中,被調(diào)用者事務(wù)傳播屬性為NESTED佣谐,當(dāng)出現(xiàn)異常時(shí)肚吏, 調(diào)用者把departmentService try,catch了狭魂。這個(gè)區(qū)別與REQUIRED的并不會(huì)報(bào)錯(cuò)罚攀,而且addEmpByNested方法不會(huì)回滾,只有addDeptByNested回滾了雌澄。
大概原理:當(dāng)被調(diào)用者使用PROPAGATION_NESTED時(shí)坞生,底層的數(shù)據(jù)源必須基于JDBC 3.0,并且實(shí)現(xiàn)者需要支持保存點(diǎn)事務(wù)機(jī)制掷伙。按上述代碼來(lái)說(shuō)(去掉try,catch)又兵,當(dāng)執(zhí)行到addDeptByNested這個(gè)方法時(shí)任柜,Spring會(huì)為它創(chuàng)建一個(gè)內(nèi)部的嵌套事務(wù),如果addDeptByNested執(zhí)行失敗沛厨,則事務(wù)回滾到addDeptByNested之前的點(diǎn)宙地,此時(shí)如果不拋異常,則不會(huì)回滾逆皮。這個(gè)嵌套事務(wù)宅粥,是addEmpByNested的一部分,只有外層事務(wù)提交了电谣,內(nèi)層的嵌套事務(wù)才會(huì)一起提交秽梅,這也是與REQUIRED(加入事務(wù))抹蚀,REQUIRES_NEW(開(kāi)啟新事務(wù))的區(qū)別。
還值得一提的是企垦,NESTED是嵌套的意思环壤,其實(shí)并不是只有NESTED用于嵌套,只要理解上述7個(gè)傳播機(jī)制的意思钞诡,都可以嵌套用郑现。

github:https://github.com/zycisbg/transaction-propagate

下邊是一個(gè)我同事總結(jié)的圖。非常精確荧降,簡(jiǎn)短接箫。
大神同事syq的圖 (⊙0⊙).png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市朵诫,隨后出現(xiàn)的幾起案子辛友,更是在濱河造成了極大的恐慌,老刑警劉巖拗窃,帶你破解...
    沈念sama閱讀 206,482評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件瞎领,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡随夸,警方通過(guò)查閱死者的電腦和手機(jī)九默,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)宾毒,“玉大人驼修,你說(shuō)我怎么就攤上這事≌╊酰” “怎么了乙各?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,762評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀(guān)的道長(zhǎng)幢竹。 經(jīng)常有香客問(wèn)我耳峦,道長(zhǎng),這世上最難降的妖魔是什么焕毫? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,273評(píng)論 1 279
  • 正文 為了忘掉前任蹲坷,我火速辦了婚禮,結(jié)果婚禮上邑飒,老公的妹妹穿的比我還像新娘循签。我一直安慰自己,他們只是感情好疙咸,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,289評(píng)論 5 373
  • 文/花漫 我一把揭開(kāi)白布县匠。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪乞旦。 梳的紋絲不亂的頭發(fā)上贼穆,一...
    開(kāi)封第一講書(shū)人閱讀 49,046評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音杆查,去河邊找鬼扮惦。 笑死,一個(gè)胖子當(dāng)著我的面吹牛亲桦,可吹牛的內(nèi)容都是我干的崖蜜。 我是一名探鬼主播,決...
    沈念sama閱讀 38,351評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼客峭,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼豫领!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起舔琅,我...
    開(kāi)封第一講書(shū)人閱讀 36,988評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤等恐,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后备蚓,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體课蔬,經(jīng)...
    沈念sama閱讀 43,476評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,948評(píng)論 2 324
  • 正文 我和宋清朗相戀三年郊尝,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了二跋。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,064評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡流昏,死狀恐怖扎即,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情况凉,我是刑警寧澤谚鄙,帶...
    沈念sama閱讀 33,712評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站刁绒,受9級(jí)特大地震影響闷营,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜知市,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,261評(píng)論 3 307
  • 文/蒙蒙 一傻盟、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧初狰,春花似錦、人聲如沸互例。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,264評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至腥光,卻和暖如春关顷,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背武福。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,486評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工议双, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人捉片。 一個(gè)月前我還...
    沈念sama閱讀 45,511評(píng)論 2 354
  • 正文 我出身青樓平痰,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親伍纫。 傳聞我的和親對(duì)象是個(gè)殘疾皇子宗雇,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,802評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • 很多人喜歡這篇文章,特此同步過(guò)來(lái) 由淺入深談?wù)搒pring事務(wù) 前言 這篇其實(shí)也要?dú)w納到《常識(shí)》系列中莹规,但這重點(diǎn)又...
    碼農(nóng)戲碼閱讀 4,706評(píng)論 2 59
  • Spring 事務(wù)屬性分析 事務(wù)管理對(duì)于企業(yè)應(yīng)用而言至關(guān)重要赔蒲。它保證了用戶(hù)的每一次操作都是可靠的,即便出現(xiàn)了異常的...
    壹點(diǎn)零閱讀 1,295評(píng)論 0 2
  • 一、事務(wù)的基本原理 Spring事務(wù)的本質(zhì)其實(shí)就是數(shù)據(jù)庫(kù)對(duì)事務(wù)的支持母市,沒(méi)有數(shù)據(jù)庫(kù)的事務(wù)支持矾兜,spring是無(wú)法提供...
    芭蕾武閱讀 1,693評(píng)論 3 12
  • 在武志紅老師的《家為什么會(huì)傷人》一書(shū)中提到了在家庭關(guān)系中很重要的一點(diǎn):“感受比事實(shí)更重要”。 《兩性關(guān)系至高境界》...
    趙慧姿閱讀 387評(píng)論 0 8
  • 如何評(píng)價(jià)幼兒不合常規(guī)的行為 幼兒階段是個(gè)體自我意識(shí)萌芽階段窒篱。幼兒自尊心逐漸得到發(fā)展焕刮,開(kāi)始形成。這個(gè)...
    越同學(xué)呢閱讀 389評(píng)論 0 0