使用Grails Executor Plugin runAsync,为什么我需要一个事务来保存Domain对象?

时间:2013-10-06 14:51:00

标签: hibernate grails transactions gorm executor

这大致是我在服务中所做的事情:

runAsync 
{
  <some work here>
  myDomainObject.merge()     
}

我收到一条错误消息“没有Hibernate Session绑定到线程,配置不允许在这里创建非事务性的”。我确信代码是异步运行的,所以看起来Executor插件设置正确。

所以我接下来尝试了这个,认为域对象“myDomainObject”不能绑定在这个线程中,尽管线程有一个hibernate会话,这要归功于executor插件:

runAsync
{
  <work>
  def instance2= MyDomainObject.get(myDomainObject.id) // works
  instance2.field1=123
  instance2.save() // fails
}

我在这里得到了同样的错误,有趣的是,get()成功地获取了正确的数据并将其设置为instance2。只有“save()”失败了。我知道这是因为我在调试器中逐步完成了代码。

最后,如果我执行以下操作,一切正常:

runAsync 
    {
      <some work here>
      MyDomainObject.withTransaction {
           myDomainObject.field1=123
           myDomainObject.merge()
      }
    }

我不明白为什么这个事务是必需的,因为我没有设置我正在编写上述代码的服务是事务性的。我知道必须有一些我不知道的基本内容,但我不知道它是什么。

1 个答案:

答案 0 :(得分:2)

看起来你回答了自己的问题:)

我不明白为什么这个交易是必需的,因为我没有设置服务我将上面的代码写成交易

查看NOTE ON TRANSACTIONS。您需要将服务作为交易服务。

  

交易注意事项:请记住,这是一个新的交易   线程和任何调用将在您的交易之外   in。在闭包内使用.withTransaction,可运行或可调用   让你的进程在一个没有调用的事务中运行   事务性服务方法(例如在使用此方法时)   控制器)。

<强>更新
尝试如下的服务类:

class MyService{

    def someMethod(){
        runAsync {
            anotherMethod()
        }
    }

    def anotherMethod(){ 
       <work>
       def instance2= MyDomainObject.get(myDomainObject.id) // works
       instance2.field1=123
       instance2.save() // should work as well
    }
}