Spring 即使在非事务方法或控制器中捕获到异常,事务方法也会回滚
Spring transactional method gets rollback even if exception is catched in non-transactional method or in controller
我在非事务性方法中调用 try-catch 块内的两个事务性方法。发生异常时,我能够捕获异常并将其记录下来。第一个事务方法不会回滚,但最后一个会。这种行为是我目前在 spring 事务管理中的理解。
public void grab(){
try{
requestManager.updateRequest();
requestManager.saveTicket()
}catch (DataIntegrityViolationException dive) {
if (dive.getCause() instanceof ConstraintViolationException) {
LOGGER.error("ConstraintViolationException",dive);
}
}
}
在上面的代码中,ConstraintViolationException 发生在 saveTicket() 方法内部,并且 saveTicket() 内部的 dao 甚至在捕获异常之前就已经回滚了它的事务(这是我所知道的),第一个没有得到回滚,因为它在另一个事务中。(这是我已经知道的行为)。
当我使用另一种调用这两个预览方法(updateRequest() 和 saveTicket())的事务方法时,我感到困惑,即使在 saveTicket() 方法中发生 ConstraintViolationException 时,即使捕获到 updateRequest() 方法也会回滚例外。这是我的代码
public void grab(){
try{
requestManager.grabRequest();
}catch (DataIntegrityViolationException dive) {
if (dive.getCause() instanceof ConstraintViolationException) {
LOGGER.error("ConstraintViolationException",dive);
}
}
}
我所知道的是,这两种方法将在 grabRequest() 方法中加入相同的事务,但我的问题是,为什么即使我正在捕获异常,事务也会回滚?这是否意味着 spring 使用的代理甚至在我捕捉到异常之前就已经回滚了事务?
Does this mean that the proxy that spring uses already rolled back the transaction even before i catch the exception?
是的,在 JPA/Spring 注释中,您可以在 @Transactional
中指定事务管理器必须回滚或不得回滚的异常列表
In its default configuration, the Spring Framework’s transaction infrastructure code only marks a transaction for rollback in the case of runtime, unchecked exceptions; that is, when the thrown exception is an instance or subclass of RuntimeException. ( Errors will also - by default - result in a rollback). Checked exceptions that are thrown from a transactional method do not result in rollback in the default configuration.
来自http://docs.spring.io/spring-framework/docs/4.2.x/spring-framework-reference/html/transaction.html
对于 JPA,它是 rollbackOn
和 dontRollbackOn
我在非事务性方法中调用 try-catch 块内的两个事务性方法。发生异常时,我能够捕获异常并将其记录下来。第一个事务方法不会回滚,但最后一个会。这种行为是我目前在 spring 事务管理中的理解。
public void grab(){
try{
requestManager.updateRequest();
requestManager.saveTicket()
}catch (DataIntegrityViolationException dive) {
if (dive.getCause() instanceof ConstraintViolationException) {
LOGGER.error("ConstraintViolationException",dive);
}
}
}
在上面的代码中,ConstraintViolationException 发生在 saveTicket() 方法内部,并且 saveTicket() 内部的 dao 甚至在捕获异常之前就已经回滚了它的事务(这是我所知道的),第一个没有得到回滚,因为它在另一个事务中。(这是我已经知道的行为)。
当我使用另一种调用这两个预览方法(updateRequest() 和 saveTicket())的事务方法时,我感到困惑,即使在 saveTicket() 方法中发生 ConstraintViolationException 时,即使捕获到 updateRequest() 方法也会回滚例外。这是我的代码
public void grab(){
try{
requestManager.grabRequest();
}catch (DataIntegrityViolationException dive) {
if (dive.getCause() instanceof ConstraintViolationException) {
LOGGER.error("ConstraintViolationException",dive);
}
}
}
我所知道的是,这两种方法将在 grabRequest() 方法中加入相同的事务,但我的问题是,为什么即使我正在捕获异常,事务也会回滚?这是否意味着 spring 使用的代理甚至在我捕捉到异常之前就已经回滚了事务?
Does this mean that the proxy that spring uses already rolled back the transaction even before i catch the exception?
是的,在 JPA/Spring 注释中,您可以在 @Transactional
In its default configuration, the Spring Framework’s transaction infrastructure code only marks a transaction for rollback in the case of runtime, unchecked exceptions; that is, when the thrown exception is an instance or subclass of RuntimeException. ( Errors will also - by default - result in a rollback). Checked exceptions that are thrown from a transactional method do not result in rollback in the default configuration.
来自http://docs.spring.io/spring-framework/docs/4.2.x/spring-framework-reference/html/transaction.html
对于 JPA,它是 rollbackOn
和 dontRollbackOn