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