javascript
Spring事务管理--嵌套事务详解
轉(zhuǎn)載自?https://www.2cto.com/kf/201607/529762.html
一、前言
最近開發(fā)程序的時(shí)候,出現(xiàn)數(shù)據(jù)庫自增id跳數(shù)字情況,無奈之下dba遍查操作日志,沒有delete記錄。才開始慢慢來查詢事物問題。多久以來欠下的賬,今天該還給spring事物。 希望大家有所收獲。2016年07月19日22:32:38
二、spring嵌套事物
1、展示項(xiàng)目代碼--簡單測springboot項(xiàng)目
整體項(xiàng)目就這么簡單,為了方便。這里就只有biz層與service層,主要作為兩層嵌套,大家只要看看大概就ok。后面會(huì)給出git項(xiàng)目地址,下載下來看一看就明白,力求最簡單。
下面我們分情況介紹異常。
Controller 調(diào)用層(沒有使用它作為外層,因?yàn)閏ontroller作為外層要在servlet-mvc.xml 配置就ok。但是我覺得比較麻煩,一般也不推薦)
?| 1 | package com.ycy.app; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; import org.springframework.context.annotation.ImportResource; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * Created by ycy on 16/7/19. */ @RestController @SpringBootApplication @EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class}) @ImportResource({"classpath:/applicationContext.xml"}) public class Application { @Autowired private TestBiz testBiz; @RequestMapping("/") String home() throws Exception { System.out.println("controller 正常執(zhí)行"); testBiz.insetTes(); return " 正常返回Hello World!"; } public static void main(String[] args) throws Exception { SpringApplication.run(Application.class, args); } } |
| 1 | package com.ycy.app; import com.ycy.service.TestService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; /** * Created by ycy on 16/7/20. */ @Component public class TestBiz { @Autowired private TestService testService; @Transactional public void insetTes() { for (int j = 0; j < 8; j++) { testService.testInsert(j, j + "姓名"); } System.out.println("biz層 正常執(zhí)行"); } } |
?
| 1 | package com.ycy.service.impl; import com.ycy.center.dao.entity.YcyTable; import com.ycy.center.dao.mapper.YcyTableMapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; /** * Created by ycy on 16/7/19. */ @Service public class TestServiceImpl implements com.ycy.service.TestService { @Autowired private YcyTableMapper ycyTableMapper; @Transactional public void testInsert(int num,String name) { YcyTable ycyTable=new YcyTable(); ycyTable.setName(name); ycyTable.setNum(num); ycyTableMapper.insert(ycyTable); System.out.println(num+"service正常執(zhí)行"); } } |
?
2、外部起事物,內(nèi)部起事物,內(nèi)外都無Try Catch外部異常:
代碼展示,修改外層Biz層代碼如下
@Component public class TestBiz { @Autowired private TestService testService; @Transactional public void insetTes() { for (int j = 0; j < 8; j++) { testService.testInsert(j, j + "姓名"); if (j == 3) { int i = 1 / 0;// 此處會(huì)產(chǎn)生異常 } } System.out.println("biz層 正常執(zhí)行"); } }打印執(zhí)行結(jié)果:0-3service正常執(zhí)行 數(shù)據(jù)庫結(jié)果:全部數(shù)據(jù)回滾
外部異常總結(jié):內(nèi)外都無try Catch的時(shí)候,外部異常,全部回滾。
?
內(nèi)部異常:
代碼展示,修改service層代碼
?| 12345678910111213141516171819202122232425262728293031 | package com.ycy.service.impl;import com.ycy.center.dao.entity.YcyTable;import com.ycy.center.dao.mapper.YcyTableMapper;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import org.springframework.transaction.annotation.Transactional;/**?* Created by ycy on 16/7/19.?*/@Servicepublic class TestServiceImpl implements com.ycy.service.TestService {??@Autowired??private YcyTableMapper ycyTableMapper;??@Transactional??public void testInsert(int num, String name) {????YcyTable ycyTable = new YcyTable();????ycyTable.setName(name);????ycyTable.setNum(num);????ycyTableMapper.insert(ycyTable);????if (num == 3) {??????int i = 1 / 0;// 此處會(huì)產(chǎn)生異常????}????System.out.println(num + "service正常執(zhí)行");??}} |
打印執(zhí)行結(jié)果:0-3service正常執(zhí)行 數(shù)據(jù)庫結(jié)果:全部數(shù)據(jù)回滾
內(nèi)部異常總結(jié):內(nèi)外都無try Catch的時(shí)候,內(nèi)部異常,全部回滾。?
3、外部起事物,內(nèi)部起事物,外部有Try Catch
外部異常:
代碼展示,修改biz層代碼
?| 1234567891011121314151617181920 | @Componentpublic class TestBiz {??@Autowired??private TestService testService;??@Transactional??public void insetTes() {????try {??????for (int j = 0; j < 8; j++) {????????testService.testInsert(j, j + "姓名");????????if (j == 3) {??????????int i = 1 / 0;// 此處會(huì)產(chǎn)生異常????????}??????}????} catch (Exception ex) {??????System.out.println("異常日志處理");????}????System.out.println("biz層 正常執(zhí)行");??}} |
?
外部異常總結(jié):外部有try Catch時(shí)候,外部異常,不能回滾(事物錯(cuò)誤)
?
內(nèi)部異常:
代碼展示,修改service層代碼:
?| 123456789101112131415161718 | @Servicepublic class TestServiceImpl implements com.ycy.service.TestService {??@Autowired??private YcyTableMapper ycyTableMapper;??@Transactional??public void testInsert(int num, String name) {????YcyTable ycyTable = new YcyTable();????ycyTable.setName(name);????ycyTable.setNum(num);????ycyTableMapper.insert(ycyTable);????if (num == 3) {??????int i = 1 / 0;// 此處會(huì)產(chǎn)生異常????}????System.out.println(num + "service正常執(zhí)行");??}} |
?
4、外部起事物,內(nèi)部起事物,內(nèi)部有Try Catch
外部異常:
代碼展示,修改biz層:
?| 12345678910111213141516 | @Componentpublic class TestBiz {??@Autowired??private TestService testService;??@Transactional??public void insetTes() {????for (int j = 0; j < 8; j++) {??????testService.testInsert(j, j + "姓名");??????if (j == 3) {????????int i = 1 / 0;// 此處會(huì)產(chǎn)生異常??????}????}????System.out.println("biz層 正常執(zhí)行");??}} |
打印結(jié)果:0-3service打印正常 數(shù)據(jù)庫結(jié)果:無數(shù)據(jù),全部數(shù)據(jù)回滾
外部異常總結(jié):內(nèi)部有try Catch,外部異常,全部回滾
?
內(nèi)部異常:
修改service層代碼:
?| 12345678910111213141516171819202122 | @Servicepublic class TestServiceImpl implements com.ycy.service.TestService {??@Autowired??private YcyTableMapper ycyTableMapper;??@Transactional??public void testInsert(int num, String name) {????try {??????YcyTable ycyTable = new YcyTable();??????ycyTable.setName(name);??????ycyTable.setNum(num);??????ycyTableMapper.insert(ycyTable);??????if (num == 3) {????????int i = 1 / 0;// 此處會(huì)產(chǎn)生異常??????}????} catch (Exception ex) {??????System.out.println(num + "service異常日志");????}????System.out.println(num + "service正常執(zhí)行");??}} |
打印結(jié)果:0-0service打印正常 數(shù)據(jù)庫結(jié)果:沒有回滾
內(nèi)部異常總結(jié):內(nèi)部有try Catch,內(nèi)部異常,全部不回滾(事物失敗);?
5、外部起事物,內(nèi)部起事物,內(nèi)外有Try Catch
外部異常:
代碼展示,修改biz層:
?| 1234567891011121314151617181920 | @Componentpublic class TestBiz {??@Autowired??private TestService testService;??@Transactional??public void insetTes() {????try {??????for (int j = 0; j < 8; j++) {????????testService.testInsert(j, j + "姓名");????????if (j == 3) {??????????int i = 1 / 0;// 此處會(huì)產(chǎn)生異常????????}??????}????} catch (Exception ex) {??????System.out.println("biz層異常日志處理");????}????System.out.println("biz層 正常執(zhí)行");??}} |
打印結(jié)果:0-3service打印正常 數(shù)據(jù)庫結(jié)果:插入三條數(shù)據(jù),沒有回滾
外部異常總結(jié):內(nèi)外都有try Catch,外部異常,事物執(zhí)行一半(事物失敗)
內(nèi)部異常:
代碼展示,修改service 層代碼
?| 123456789101112131415161718192021 | @Servicepublic class TestServiceImpl implements com.ycy.service.TestService {??@Autowired??private YcyTableMapper ycyTableMapper;??@Transactional??public void testInsert(int num, String name) {????try {??????YcyTable ycyTable = new YcyTable();??????ycyTable.setName(name);??????ycyTable.setNum(num);??????ycyTableMapper.insert(ycyTable);??????if (num == 3) {????????int i = 1 / 0;// 此處會(huì)產(chǎn)生異常??????}????} catch (Exception ex) {??????System.out.println(num + "service異常日志處理");????}????System.out.println(num + "service正常執(zhí)行");??}} |
打印結(jié)果:0-7service打印正常,3異常日子好 數(shù)據(jù)庫結(jié)果:插入全部,沒有回滾
內(nèi)部事物總結(jié):內(nèi)外都有try Catch,內(nèi)部異常,事物全部不會(huì)滾(事物失敗)?
三、嵌套事物總結(jié)
事物成功總結(jié)
1、內(nèi)外都無try Catch的時(shí)候,外部異常,全部回滾。
2、內(nèi)外都無try Catch的時(shí)候,內(nèi)部異常,全部回滾。
3、外部有try Catch時(shí)候,內(nèi)部異常,全部回滾
4、內(nèi)部有try Catch,外部異常,全部回滾
5、友情提示:外層方法中調(diào)取其他接口,或者另外開啟線程的操作,一定放到最后!!!(因?yàn)檎{(diào)取接口不能回滾,一定要最后來處理)
?
總結(jié):由于上面的異常被捕獲導(dǎo)致,很多事務(wù)回滾失敗。如果一定要將捕獲,請捕獲后又拋出RuntimeException(默認(rèn)為異常捕獲RuntimeException)。
?
四、正確的嵌套事物實(shí)例
controller層
?| 1234567891011121314151617181920212223242526272829303132333435363738 | package com.ycy.app;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.EnableAutoConfiguration;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;import org.springframework.context.annotation.ImportResource;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;/**?* Created by ycy on 16/7/19.?*/@RestController@SpringBootApplication@EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class})@ImportResource({"classpath:/applicationContext.xml"})public class Application {??@Autowired??private TestBiz testBiz;??@RequestMapping("/")??String home()? {????System.out.println("controller 正常執(zhí)行");????try {??????testBiz.insetTes();????} catch (Exception e) {??????System.out.println("controller 異常日志執(zhí)行");????}????return " 正常返回Hello World!";??}??public static void main(String[] args) throws Exception {????SpringApplication.run(Application.class, args);??}} |
?
外層biz層:
?| 123456789101112131415161718192021222324252627282930313233 | package com.ycy.app;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import org.springframework.transaction.annotation.Transactional;import com.ycy.service.TestService;/**?* Created by ycy on 16/7/20.?*/@Componentpublic class TestBiz {??@Autowired??private TestService testService;??@Transactional??public void insetTes() throws Exception {????try {??????for (int j = 0; j < 8; j++) {????????testService.testInsert(j, j + "姓名");????????if (j == 3) {??????????int i = 1 / 0;// 此處會(huì)產(chǎn)生異常????????}??????}????} catch (Exception ex) {??????System.out.println("biz層異常日志處理");??????throw new RuntimeException(ex);????}????System.out.println("biz層 正常執(zhí)行");??}} |
?
內(nèi)層service層
?| 123456789101112131415161718192021222324252627282930313233 | package com.ycy.service.impl;import com.ycy.center.dao.entity.YcyTable;import com.ycy.center.dao.mapper.YcyTableMapper;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import org.springframework.transaction.annotation.Transactional;/**?* Created by ycy on 16/7/19.?*/@Servicepublic class TestServiceImpl implements com.ycy.service.TestService {??@Autowired??private YcyTableMapper ycyTableMapper;??@Transactional??public void testInsert(int num, String name) throws Exception {????try {??????YcyTable ycyTable = new YcyTable();??????ycyTable.setName(name);??????ycyTable.setNum(num);??????ycyTableMapper.insert(ycyTable);??????if (num== 3) {????????int i = 1 / 0;// 此處會(huì)產(chǎn)生異常??????}????} catch (Exception ex) {??????System.out.println(num + "service異常日志處理");????????throw new RuntimeException(ex);????}????System.out.println(num + "service正常執(zhí)行");??}} |
總結(jié)
以上是生活随笔為你收集整理的Spring事务管理--嵌套事务详解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MySQL的or/in/union与索引
- 下一篇: Spring基础篇——Spring容器和