栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

【Java|sql|事务异常】Transaction rolled back because it has been marked as rollback-only

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【Java|sql|事务异常】Transaction rolled back because it has been marked as rollback-only

问题:

methodA方法的异常被methodB方法捕获捕获,但并未抛出,事务仅被标记rollback,而事务继续提交,最后事务提交校验时抛出Transaction rolled back because it has been marked as rollback-only异常。注意:此时内层事务和外层事务为同一事务。

@Transactional(rollbackFor = Exception.class)
public void methodA(){
	insert();
	System.out.println(1 / 0);
}

@Transactional(rollbackFor = Exception.class)
public void methodB(){
	try{
		methodA();
	}catch(Exception e){
		System.out.println("有异常");
	}
}

解释:

当spring开启事务时,如果不修改propagation的参数,则默认是propagation.REQUIRED。即如果有没有事务则新启一个事务,如果已经存在事务则加入这个事务。
当内层事务异常的情况下,如果是这种传播方式,正常来讲是需要回滚的,但是spring只是给内层事务做了一个rollback的标记。所以当内层事务抛出的异常被外层try-----catch捕获(未抛出)时,外层事务正常执行,但在最后提交的时候发现,内层被标记了rollbck,所以就会抛出Transaction rolled back because it has been marked as rollback-only这个异常信息。

解决方案

如果我们需要内层异常的情况下,回滚整个事务,可以让内层事务抛出的异常被外层事务的try----catch处理,再抛出新的异常,或者外层不通过try—catch处理这个异常。

@Transactional(rollbackFor = Exception.class)
public void methodA(){
	System.out.println(1 / 0);
}

@Transactional(rollbackFor = Exception.class)
public void methodB(){
	try{
		insert();
		methodA();
	}catch(Exception e){
		throw new Exception("存在异常")
	}
}

如果内层事务异常的情况下只回滚内层事务,修改内层事务的事务传播方式(不建议)

@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
public void methodA(){
	System.out.println(1 / 0);
}

@Transactional(rollbackFor = Exception.class)
public void methodB(){
	try{
		insert();
		methodA();
	}catch(Exception e){
		System.out.println("有异常");
	}
}

@Transactional(propagation = Propagation.REQUIRES_NEW)
@Transactional
public CommonReturnType funA() {
	//...
	funB(); // 调用函数B
	//...
	func(); // 调用函数C
	//...
}

@Transactional(propagation = Propagation.REQUIRES_NEW)
public void funB() {
	//...
}

@Transactional(propagation = Propagation.REQUIRES)
public void funC() {
	//...
}


Spring遇到嵌套事务时,当被嵌套的事务被定义为“PROPAGATION_REQUIRES_NEW”时,
内层Service的方法被调用时,外层方法的事务被挂起;
内层事务相对于外层事务是完全独立的,有独立的隔离性;
新的执行完毕,继续执行老的事务

当出现异常时:
1、当方法B或者C报错时,A、B、C方法都回滚
2、当方法A、B、C异常被捕获时,A、B、C事务不回滚(a、b、c均入库)
3、当方法BC执行后,方法A报错时,A、C事务回滚,B事务不回滚(b数据入库)

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1025060.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号