Grails和hibernate会话,在异常时保存到数据库

时间:2015-01-28 13:52:37

标签: hibernate session exception grails transactions

我正在使用Grails框架。

想要在失败时将某些内容保存到数据库(在抛出RuntimeException之后)。假设我在一个交易服务中有类似的东西:

try {
   throw new RuntimeException()
} catch(Exception ex) {
   new FatalErrorDomainObject().save()
}

当前版本将失败,因为会话设置为回滚。

我试图以多种方式解决这个问题,到目前为止我发现的是:

.withTransaction - 将无效,因为将事务绑定到当前会话

.withSession - 无效,因为只会重复使用现有会话

.withNewSession - 单独不起作用,因为它将在同一个线程中创建新会话(相同的线程=相同的数据库连接,因此它将因SQL异常而失败)

到目前为止,我找到的唯一可行解决方案是创建新线程和新的hibernate会话。它真的是唯一(和正确)的方式来实现这个目标吗?

public static void syncSession(Closure job) {
    // Checking environment in production code it's not very elegant but thanks to this it's transparent
    // for all tests and makes them DRY.
    if(Environment.current == Environment.TEST) {
        job.call()
    }
    Thread t = new Thread({
        DomainObject.withNewSession {
            job.call()
        }
    })
    t.start()
    t.join()
}

用法:

try {
   throw new RuntimeException()
} catch(Exception ex) {
   syncSession {
      new FatalErrorDomainObject().save()
   }
}

1 个答案:

答案 0 :(得分:0)

我认为您的解决方案更好,但我还是考虑过给您提出这样的建议:在其他逻辑之前的单独事务之前调用new FatalErrorDomainObject().save(),之后再调用def fatalError = new FatalErrorDomainObject() FatalErrorDomainObject.withTransaction { status -> fatalError.save() } doSomethingThatMightThrowRuntimeException() FatalErrorDomainObject.get(fatalError.id).delete() 提交,删除FatalErrorDomainObject。像这样:

{{1}}