[英]Spring transaction and try catch blocks
我对 Kotlin 和 Spring 非常陌生,并且有一个非常基本的疑问。 考虑这样的 function:
@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
}
微不足道地从不实际提交任何东西,这可能很明显。 否则,该方法退出,它可以通过以下三种方式之一退出:
throw new RuntimeException()
)。throw new IOException()
添加到 accept 方法的末尾,当然您的方法可以这样做。在 java 中意味着它必须当然,被声明为void accept() throws IOException {}
。kotlin中不存在已检查和未检查的概念 - 在 kotlin 中,所有异常都是“未检查”,有效。 但是,spring 没有 go:“OOoooohhhh,kotlin 用户,我将把所有事情都视为未选中的事务,即抛出任何异常,” 不,因此,即使您只编写 kotlin,您也必须了解检查异常是什么。
Unchecked exceptions are all throwables that have in their type hierarchy either java.lang.Error
(such as java.lang.InternalError
, which extends jlError
), or java.lang.RuntimeException
, such as NullPointerException
.
所有其他投掷物都被“检查”。 比如IOException
,它扩展了 Exception。 它扩展了 Throwable。 检查Exception
本身。
注意:您可以添加拦截器等来改变这种行为; “检查异常意味着我们需要提交,检查意味着我们需要中止”只是默认行为。
如果“写入表 A”成功,那么是的,它将持续存在。
为什么? 因为事务划分是由对异常起作用的拦截器完成的,并且在您的代码中没有拦截器会看到该异常,因为它们只能围绕那些“写入表 X”调用(如果这些调用是通过可拦截代码完成的)或accept()
执行。
让我尝试添加更多细节:
一般来说,您可以在概念上认为拦截器看起来像这样(它们看起来不同,但示例用于说明这一点 - 我还将使用 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()
中被抛出和捕获 - 因此不会离开方法 - 拦截器甚至不会看到它,因此将提交事务。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.