【问题标题】:Grails async Event handler fails to retrieve domain instance from persistenceGrails 异步事件处理程序无法从持久性中检索域实例
【发布时间】:2017-01-09 00:54:21
【问题描述】:

我正在尝试在事务服务中创建和持久化一个 Foo 实例,然后在持久化 Foo 实例后,触发一个事件以对其进行一些异步处理。

我遇到的问题是,当我尝试从事件处理程序中的持久性中检索 Foo 实例时,找不到该实例。

我的保持Foo 实例的服务方法如下所示:

Foo makeFoo() {
  def foo = new Foo(...).save(flush: true, failOnError: true)
  notify("FOO_CREATED_EVT", foo.id)
  return foo
}

我的事件处理程序存在于单独的事务服务中,如下所示:

@Selector("FOO_CREATED_EVT")
void onFooCreated(Long fooId) {
  def foo = Foo.get(fooId) // also tried findById, with the same outcome
  assert foo != null // fails
}

我已经在启用 sql 日志记录的情况下逐步检查了双方的代码,并验证了Foo 实例成功地保存在makeFoo() 中,但是当onFooCreated() 尝试检索它时,它总是失败。据我所知,在触发事件之前刷新保存应该会导致 Foo 实例立即被持久化,但是如果我在 onFooCreated 中添加延迟:

Thread.sleep(1000)
def foo = Foo.get(fooId)
assert foo != null // succeeds

那么操作成功了,所以我只能假设存在竞争条件,因为flush实际上并没有同步持久化实例。

我的项目使用带有 Hibernate 5 和 PostgreSQL 9.6 的 Grails 3.2。

我显然做错了什么,但是关于异步事件的文档非常稀少,并且在解决这种情况时遇到了困难:(

【问题讨论】:

    标签: hibernate grails asynchronous grails-orm


    【解决方案1】:

    flush() 可能已执行,但事务尚未提交或关闭,因此数据对另一个线程不可见,因为事务是隔离的,另一个线程将使用单独的连接。

    在触发事件之前,您需要确保事务已提交。

    【讨论】:

    • 感谢 Graeme - 这是有道理的。我确定这是从 Hibernate 继承的行为,但是当我们讨论这个主题时,这种行为不会违背 flush() 的目的吗?
    猜你喜欢
    • 1970-01-01
    • 2013-02-09
    • 1970-01-01
    • 1970-01-01
    • 2016-09-06
    • 1970-01-01
    • 2011-09-15
    • 1970-01-01
    • 2011-09-11
    相关资源
    最近更新 更多