【问题标题】:Grails and hibernate session, save to database on exceptionGrails 和休眠会话,异常时保存到数据库
【发布时间】:2015-01-28 13:52:36
【问题描述】:

我正在使用 Grails 框架。

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

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

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

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

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

.withSession - 不起作用,因为只会重用现有会话

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

到目前为止,我发现的唯一可行的解​​决方案是创建新线程和新的休眠会话。这真的是实现这一目标的唯一(也是正确)方法吗?

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()
   }
}

【问题讨论】:

    标签: hibernate session exception grails transactions


    【解决方案1】:

    我认为你的解决方案更好,但我还是想给你这个建议:在一个单独的事务中调用new FatalErrorDomainObject().save()你的其余逻辑之前,在它的最后,在提交之前,删除 FatalErrorDomainObject。像这样的:

    def fatalError = new FatalErrorDomainObject()
    FatalErrorDomainObject.withTransaction { status ->
        fatalError.save()
    }
    doSomethingThatMightThrowRuntimeException()
    FatalErrorDomainObject.get(fatalError.id).delete()
    

    【讨论】:

    • 这个错误对象用于通知发生了错误,它会标记所有调用都是错误的(例如通过电子邮件传播错误),然后我会默默地删除它。在我的情况下不起作用,但感谢您的建议。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-08-07
    • 2013-05-18
    • 1970-01-01
    • 2014-01-01
    • 1970-01-01
    • 2014-10-25
    • 2015-06-12
    相关资源
    最近更新 更多