我的代码使用带有以下代码的Spring,Hibernate和DB2:
@Transactional
doSth(){
Object obj = dao.getObject();
try{
classA.methodA(obj);
}catch(Exception ex){
classB.methodB(obj);
}
}
ClassA:
methodA(Object obj){
obj.setStatus("successful");
throw new RuntimeException();
}
ClassB:
@Transational(propagation=REQUIRES_NEW)
methodB(Object obj){...
obj.setStatus("failed");
}
methodA
does not have @Transactional annotation and will use doSth
's transaction
Both methodA and methodB are updating same record obj
of a table.
With the given code, when exception is thrown in methodA after obj.setStatus("successful")
, methodB will be stuck and wait forever.
I suppose, this is because when methodB
is trying to update obj
, the transaction used by methodA
is not yet rolled back and it holds some db lock against obj
.
So methodB
is waiting for the lock from methodA
, while methodA
needs methodB
to finish to rollback and release the lock, resulting in deadlock.
如我所测试,要解决此问题,有两种方法:
Let the exception be thrown before
obj.setStatus("successful")
, so thatobj
is not yet updated bymethodA
Make
methodA
use@Transational(propagation=REQUIRES_NEW)
, so that its transaction is already rolled back by the timemethodB
is triggered
有人可以验证我的理解是否正确吗?这意味着如果两个事务的事务边界彼此重叠,则永远不要尝试更新同一记录。