Spring事务和try-catch块



我对Kotlin和Spring很陌生,有一个非常基本的疑问。考虑这样一个函数:

@transaction
fun accept() {
try {
write to table A
throw Exception()
} catch(){
write to table B
}
}

问题:我知道表B写会成功,但表A写会成功吗?为什么?任何指向的指针

Spring对异常的"含义"有点奇怪。其作用如下。事务方法在退出之前不会提交任何内容。即:

@transaction
fun accept() {
write to table A
while (true) {} // loop forever
}

微不足道的是,从来没有真正提交过任何东西,这可能是显而易见的。否则,该方法将退出,并且可以通过以下三种方式之一退出:

  • 方法"return"。与中一样,不会从方法中抛出任何异常——可能会抛出异常,但它们会被捕获。然后,在退出该方法时,事务被提交请注意,这描述了您的代码段,它不会抛出方法的异常。因此,对表A和表B的写入都将发生,并且可以从外部看到
  • 该方法通过抛出一个未检查的异常来结束。Spring认为这是"意外的",并表明执行该方法的结果是失败的——整个事务被中止。对表A的写入对其他事务永远都不可见,对表B的写入也不可见(假设在catch块之后,您有未选中的throw new RuntimeException()(
  • 该方法以抛出CHECKED异常结束。Spring的观点是,这一定意味着它是"有意的",并表明代码成功了;它只是简单地选择了";返回";一个异常而不是正常结束。事务已提交-对表A的写入将对其他人可见。对表B的写入也将对其他人可见(这是假设您将throw new IOException()添加到accept方法的末尾,当然也允许您的方法这样做。这在java中意味着它必须声明为void accept() throws IOException {}

在kotlin中不存在检查和未检查的概念-在kotling中,所有异常都是"未检查"的,有效。然而,春天不去:;OOoooohhhh,kotlin用户,我会把一切都当作未检查一样对待,即任何抛出的异常都会导致事务中止;。不,所以,即使只写kotlin,您也必须了解什么是检查异常

未选中的异常是在其类型层次结构中具有java.lang.Error(例如扩展j.l.Errorjava.lang.InternalError(或java.lang.RuntimeException(例如NullPointerException(的所有可丢弃的异常。

所有其他一次性物品都经过"检查"。例如IOException,它扩展了Exception。其延伸了Throwable。Exception本身被检查

注意:你可以添加拦截器等来改变这种行为"checked exception表示我们需要提交,checked表示我们需要中止";只是默认行为。

如果"写入表A";如果成功,那么是的,它将持续下去。

为什么?因为事务划分是由对异常采取行动的拦截器完成的,并且在您的代码中,没有拦截器会看到该异常,因为它们只能围绕这些"异常"执行;写入表X";调用(如果这些调用是通过可截获代码完成的(或CCD_ 11。

让我尝试添加更多细节:

一般来说,你可以从概念上认为拦截器是这样的(它们看起来不同,但这个例子是用来说明这一点的——我也会使用Java代码,因为我不太熟悉Kotlin(:

void runInTransaction(Runnable interceptedCode) {
Transaction tx = startTransaction();
try {
interceptedCode.run();
tx.commit();
} catch( Exception e) { //kept simple for illustration purposes, in reality this is way more complex
tx.rollback();
}
}

然后你会这样称呼它:

runInTransaction(() -> accept());

正如您所看到的,由于异常只在accept()中抛出和捕获,因此不会离开方法,因此拦截器甚至看不到它,因此会提交事务。

最新更新