Grails异步事件处理程序无法从持久性中检索域实例

时间:2017-01-09 00:54:22

标签: hibernate grails asynchronous gorm

我正在尝试在事务服务中创建并持久化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实际上不是同步持久化实例。

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

我显然做错了什么但是异步事件的文档非常稀疏,并且在这个场景中遇到了问题:(

1 个答案:

答案 0 :(得分:1)

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

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