[英]Grails and hibernate session, save to database on exception
I'm using Grails framework. 我正在使用Grails框架。
Want to save something to database on failure (after RuntimeException
is thrown). 想要在失败时将某些内容保存到数据库中(引发RuntimeException
之后)。 Let's say I have something like this in one of transactional services: 假设我在一种事务服务中有这样的东西:
try {
throw new RuntimeException()
} catch(Exception ex) {
new FatalErrorDomainObject().save()
}
Current version will fail because session is set to rollback. 当前版本将失败,因为会话设置为回滚。
I tried to solve this problem in multiple ways and what I found so far is: 我试图以多种方式解决此问题,到目前为止,我发现的是:
.withTransaction
- will not work because will bind transaction to current session .withTransaction
无效,因为它将事务绑定到当前会话
.withSession
- will not work because will just reuse existing session .withSession
将不起作用,因为它将仅重用现有会话
.withNewSession
- alone will not work because it will create new session in same thread (same thread = same db connection, so it will fail with SQL exception) .withNewSession
单独将不起作用,因为它将在同一线程中创建新会话(同一线程=相同的数据库连接,因此它将因SQL异常而失败)
The only working solution I found so far is to create new thread and new hibernate session. 到目前为止,我发现的唯一可行的解决方案是创建新线程和新的休眠会话。 Is it really the only (and the right) way to accomplish this? 这真的是唯一(正确的)方法吗?
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()
}
Usage: 用法:
try {
throw new RuntimeException()
} catch(Exception ex) {
syncSession {
new FatalErrorDomainObject().save()
}
}
I think your solution is better but I thought of giving you this suggestion anyway: call new FatalErrorDomainObject().save()
in a separate transaction before the rest of your logic and at the end of it, before the commit, delete the FatalErrorDomainObject. 我认为您的解决方案更好,但是我仍然想给您这个建议:在其余逻辑之前在单独的事务中调用new FatalErrorDomainObject().save()
,并在提交结束之前在逻辑末尾删除FatalErrorDomainObject。 Something like this: 像这样:
def fatalError = new FatalErrorDomainObject()
FatalErrorDomainObject.withTransaction { status ->
fatalError.save()
}
doSomethingThatMightThrowRuntimeException()
FatalErrorDomainObject.get(fatalError.id).delete()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.