为什么抛出 NullPointerException 后 @Transactional 不回滚?
Why doesn't @Transactional roll back after NullPointerException is thrown?
我有一个可以抛出 NullPointerException 的方法。该方法标有@Transactional
.
我的代码结构如下:
public void outer() {
try {
inner();
} catch (Exception e) {
// exception caught
}
}
@Transactional
public void inner() {
database.saveStuff();
throw new NullPointerException();
}
在运行上面的代码之后,inner()
里面的数据库更新没有回滚。什么会导致这样的问题?
据我了解,如果异常对注释“可见”,则应回滚数据库操作。在这种情况下意味着 inner()
方法被标记为 @Transactional
并抛出异常而不是捕获它。
可能 还值得一提的是,方法 outer()
也在另一个 @Transactional
方法中调用,后者又在 try catch
.但是,该方法不可见该异常,因为它被捕获在 outer()
中,因此根据我的理解,这无关紧要。
我试图在网上搜索答案,但所有答案似乎都是关于检查的异常(例如java.lang.Exception
)不会自动回滚。因为 NullPointerException
是 RuntimeException
的子类,所以这不应该成为问题。
我的团队中有人也建议使用这组注释,但没有任何区别:
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Transactional(rollbackFor=Exception.class, isolation=Isolation.READ_COMMITTED)
因为您是直接调用inner()
。 Spring AOP 仅适用于 bean 方法,因为 inner()
被直接调用,不会被代理,也不会添加拦截器。
正如您提到的,outer
方法是从具有 @Transactional
的方法中调用的,因此,您应该删除 try-catch
或重新抛出异常。
我有一个可以抛出 NullPointerException 的方法。该方法标有@Transactional
.
我的代码结构如下:
public void outer() {
try {
inner();
} catch (Exception e) {
// exception caught
}
}
@Transactional
public void inner() {
database.saveStuff();
throw new NullPointerException();
}
在运行上面的代码之后,inner()
里面的数据库更新没有回滚。什么会导致这样的问题?
据我了解,如果异常对注释“可见”,则应回滚数据库操作。在这种情况下意味着 inner()
方法被标记为 @Transactional
并抛出异常而不是捕获它。
可能 还值得一提的是,方法 outer()
也在另一个 @Transactional
方法中调用,后者又在 try catch
.但是,该方法不可见该异常,因为它被捕获在 outer()
中,因此根据我的理解,这无关紧要。
我试图在网上搜索答案,但所有答案似乎都是关于检查的异常(例如java.lang.Exception
)不会自动回滚。因为 NullPointerException
是 RuntimeException
的子类,所以这不应该成为问题。
我的团队中有人也建议使用这组注释,但没有任何区别:
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Transactional(rollbackFor=Exception.class, isolation=Isolation.READ_COMMITTED)
因为您是直接调用inner()
。 Spring AOP 仅适用于 bean 方法,因为 inner()
被直接调用,不会被代理,也不会添加拦截器。
正如您提到的,outer
方法是从具有 @Transactional
的方法中调用的,因此,您应该删除 try-catch
或重新抛出异常。