Grails(2.3)@Transactional不回滚

时间:2017-02-16 20:01:12

标签: grails rollback transactional

回滚按预期完成:

@Transactional(propagation = Propagation.REQUIRES_NEW)
def test1() {
  def dummy = new Dummy(name: "test1")
  dummy.save()
  throw new RuntimeException("test1!")
}

但是这里没有 - 这可能是错误的 - try / catch不应该影响行为:

@Transactional(propagation = Propagation.REQUIRES_NEW)
def test2() {
  def dummy = new Dummy(name: "test2")
  dummy.save()
  try {
    throw new RuntimeException("test2!")
  } catch (all) {
    println all.message
  }
}

2 个答案:

答案 0 :(得分:2)

默认情况下,@Transactional包装方法,以便任何未经检查的异常(即RuntimeException)将导致事务回滚。

如果在方法中捕获/处理异常,当然,异常不会传播到事务包装器,并且事务不会被标记为仅回滚。这似乎就是你正在做的事情。

值得指出的是,如果抛出其他异常(并传播到包装器),您可以指示事务包装器应该回滚事务。您可以使用rollbackFor注释参数执行此操作。

例如,

@Transactional(rollbackFor=Throwable.class)
void doTransactionalWork() throws MyException { ... }
如果任何Throwable传播到包装器,

将导致事务回滚,即使是那些被检查的事件(即MyException

这应该是任何@Transactional方法的行为,无论您是创建新事务还是继承现有事务上下文。

答案 1 :(得分:1)

也许你误解了尝试捕获的目的,或者你可能只是有一个摇摆不定的时刻:

@Transactional(propagation = Propagation.REQUIRES_NEW)
def test2() {
  //you may be doing other stuff here
  //but now about to do some transaction work 
  //so lets wrap this method around a try catch
  try { 
    //this is happening
    def dummy = new Dummy(name: "test2")
    dummy.save()       
  } catch (Exception all) {  // or catch (Throwable all) {
     // if something went wrong in above save method
     //should be caught and runtime exception means roll back
     throw new RuntimeException("test2!" +all?.toString())
  }
}

我希望它能解释你出错的地方但是你真的希望在服务中完成所有这些并在控制器中执行try catch部分 -

所以你做交易工作,如果出现问题,你可能希望从控制器中的try catch捕获并将其设置为回滚的服务中抛出其他异常。

I did a sample project years back here希望有所帮助

无论如何这些都是某人的实验,并不是你想要做正确编码的方式,我的意思是这是一种奇怪的不寻常的做事方式,简而言之,他只是试图让它抛出运行时异常因此触发回滚。在答案中我坚持我的建议,你想在控制器中做一次尝试捕获。它试图捕获手头对象的验证错误以及任何给定服务事务工作失败的失败。 Something like this但可能需要做更多的工作来捕获所有特定问题并返回原始页面以及潜在问题 - 现在还回滚了事务。