如何使用Hibernate回滚到保存点嵌套事务

时间:2013-11-25 16:58:31

标签: spring jdbc transactions savepoints

我有一个使用Hibernate连接数据库的JavaEE应用程序。在我的应用程序的某些部分,我调用了具有@Transactional注释的方法。在某些情况下,我想回滚整个事务(外部服务方法调用和内部事务)。在某些情况下,我想只回滚内部服务方法调用(即,回滚到内部方法开头定义的保存点)。

第一部分已经到位,但我对第二部分有疑问。当我执行以下操作时,出现“UnexpectedRollbackException”,并显示消息“事务已回滚,因为它已被标记为仅回滚”。

@Service
public class OuterService{

    @AutoWired
    private InnerServcie innerService; 

    @Transactional
    public void outer(){
        try{
            innerService.inner();
        }catch(RuntimeException e){
            //if i dont throw this up, it will give me the "UnexpectedRollbackException"
            System.out.println("I cought a RuntimeException");
        }
    }
}

@Service
public class InnerServcie{
    @Transactional
    public void inner(){
        //here we insert some data into db using hibernate
        //but something goes wrong and an exception is thrown
    }
}

3 个答案:

答案 0 :(得分:6)

您要查找的功能称为保存点。严格来说,它们不是嵌套事务,而是后续SQL指令链中的里程碑,您可以回滚它们。回滚到保存点意味着使创建保存点时发出的所有指令无效,因此您可以拥有多个保存点,但只能在现在保存点之间回滚指令,而不是两个保存点之间!

Spring支持保存点,无论是手动使用JdbcTransactionObjectSupport还是使用@Transactional注释。

根据文档http://docs.spring.io/spring/docs/2.5.3/reference/transaction.html指向 9.5.7.3 ,您应该使用Propagation.NESTED

但是,您的情况可能无法使用这些选项。来自Javadoc:

  

注意:实际创建嵌套事务只会起作用   特定的交易经理。开箱即用,这仅适用于   在处理JDBC 3.0时,JDBC DataSourceTransactionManager   驱动程序。一些JTA提供程序也可能支持嵌套事务。

最后,您可以直接发出/回滚到保存点的SQL指令。

对于PostgreSQL,它将是:

SAVEPOINT foo;

ROLLBACK TO SAVEPOINT foo;

来源:http://www.postgresql.org/docs/8.2/static/sql-rollback-to.html

答案 1 :(得分:0)

Spring / Hibernate / Java EE中不支持嵌套事务。因此,要么整个事情都要回滚,要么内部事务实际上是一个新的,不同的事务,一旦成功就会提交,即使外部事务稍后回滚。

如果后者是你想要的,那么只需用

注释你的内部方法
@Transactional(propagation = Propagation.REQUIRES_NEW)

答案 2 :(得分:0)

尝试将globalRollbackOnParticipationFailure的{​​{1}}属性设置为TransactionManager

有关详细信息,请参阅http://docs.spring.io/spring/docs/3.1.4.RELEASE/javadoc-api/org/springframework/transaction/support/AbstractPlatformTransactionManager.html#setGlobalRollbackOnParticipationFailure(boolean)