spring的声明式事务问题

①BaseServices 中有两个方法 updateName(),updateFlag()

DaoServices 中有个方法updateFlag()

②UserServices 中有个方法,methodUserServices()[注解:Propagation.REQUIRES_NEW],
调用如下
[code="java"]
methodUserServices(){
try{
updateName();
}catch(){
updateFlag();
}
}
[/code]
两个方法操作的是同表、同记录,会导致一个问题,如果updateName出现异常.程序运行到updateFlag()这里没有重新开启事务,会导致一起回滚掉,
如果把updateFlag单独提取出来也就是放到DaoServices里面,注解同样为Propagation.REQUIRES_NEW,会出现 Lock wait timeout exceeded; try restarting transaction; 异常
想要达到的效果即使updateName出现异常,updateFlag这个方法要提交事务

2个回答

这个没法实现,事务死锁了。updateName()的事务(简称A),获得了那条记录的排它锁,updateName()的事务(简称B)又去请求这条记录的排它锁,事务B会一直阻塞到事务A释放锁,而事务A要释放锁必须要等待事务B完成(因为事务B是嵌套在事务A中的)。

sootv5
sootv5 明白了,你的意思是说不要在外层开启事务,得为try里面的这个方法在包一层,在这个方法上开启事务
接近 6 年之前 回复
maltab5y5
maltab5y5 更新标志的方法不能放在catch里面的,前面已经说过了,会产生死锁。要实现你这个需求,只需要在外层再包装个方法wrapperMethod(),里面先执行method(),如果method()关联的事务回滚了,再执行更新标志的方法,记住事务只能分别加在method()和更新标志的方法上,wrapperMethod()方法及其调用栈的上层不能再添加任何事务的语义,这样两个互斥的事务就串行执行了。
接近 6 年之前 回复
sootv5
sootv5 我有这样的一个需求,method(){ methodToDB1(),methodToDB2(),methodToDB3()} 然后methodToDB1是操作了A表的A记录,然后希望如果第一个方法失败,其他2、3都跟着一起回滚,然后在catch里面 更新A表的A记录一个标志位,
接近 6 年之前 回复
maltab5y5
maltab5y5 这里有笔误,第2个updateName()应为updateFlag(),即事务B是updateFlag()关联的事务。
接近 6 年之前 回复

你把这两个方法放在两个事物里面不就行了

sootv5
sootv5 放在两个事务里面,因为两个方法更新的是统一条记录,会产生死锁的
接近 6 年之前 回复
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问
相关内容推荐