Grails Quartz作业在升级后没有Hibernate会话,导致LazyInitializationException

Grails Quartz作业在升级后没有Hibernate会话,导致LazyInitializationException,grails,scheduling,quartz-scheduler,hibernate-session,Grails,Scheduling,Quartz Scheduler,Hibernate Session,我已经将Grails1.0.4应用程序升级到1.1.1。升级后,我在执行Quartz作业(使用Quartz插件0.4.1)时反复遇到异常。该插件用于通过服务使用Simple和Cron触发器手动调度作业(代码如下所述): 我的BatchJob作业设置如下: class BatchJob implements Job, InterruptableJob { static triggers = {} void execute(JobExecutionContext context) {

我已经将Grails1.0.4应用程序升级到1.1.1。升级后,我在执行Quartz作业(使用Quartz插件0.4.1)时反复遇到异常。该插件用于通过服务使用Simple和Cron触发器手动调度作业(代码如下所述):

我的BatchJob作业设置如下:

class BatchJob implements Job, InterruptableJob
{
    static triggers = {}
    void execute(JobExecutionContext context) {
        def batch = Batch.get(context.jobDetail.jobDataMap.getLongValue("batchId"))
        // the next line is "line 49" from the stack trace below
        def foo = batch.batchStatus.description
    }
}
下面是Batch.groovy(域)的缩写定义:

但是,当使用现有保存的批调用
schedulerService.schedule()
时,我收到以下异常:

org.hibernate.LazyInitializationException: could not initialize proxy - no Session
        at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:86)
        at org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsHibernateUtil.unwrapProxy(GrailsHibernateUtil.java:311)
        at org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsHibernateUtil$unwrapProxy.call(Unknown Source)
        at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:40)
        ...
        <b>at BatchJob.execute(BatchJob.groovy:49)</b>
        ...
org.hibernate.LazyInitializationException:无法初始化代理-无会话
位于org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:86)
位于org.codehaus.groovy.grails.orm.hibernate.cfg.grailshbernateutil.unwrapProxy(grailshbernateutil.java:311)
位于org.codehaus.groovy.grails.orm.hibernate.cfg.grailshbernateutil$unwrapProxy.call(未知源代码)
位于org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:40)
...
在BatchJob.execute(BatchJob.groovy:49)
...
我尝试了以下操作来解决此问题,但没有一个有效:

  • 我已经在批处理域类上指定了
    static fetchMode=[batchStatus:'eager']
  • 我在批处理域类上使用了
    静态映射={columns{batchStatus lazy:false}
  • 在作业中调用
    batch.get()
    之后,我尝试使用
    batch.attach()
在本例中,我不能使用
BatchJob.triggerNow()
,因为这只是几个示例中的一个,其他示例仍由服务调度,但可能作为cron作业或其他方式调度。我应该提到,我在升级Grails时也升级了Quartz插件;以前的Quartz版本是0.4.1-SNAPSHOT(与升级版本相反,只有0.4.1)

如何让Hibernate会话在这些手动触发的Quartz作业中正常工作?

我还向grails用户邮件列表发送了这个问题,对于这样一个更为利基的问题,这个列表似乎得到了更多的响应。如果有人出来,我会用答案更新这个问题

查看jira问题165()石英插件(您可能想查看一下)中也有一些线索。这段代码与JMS插件一起使用,它似乎工作得很好

试一试

希望这有帮助。这对我来说很有效。

查看jira第165期()石英插件中也有一些线索(您可能想查看一下)。这段代码与JMS插件一起使用,似乎工作得很好

试一试


希望这有帮助。这对我很有用。

对于最新的grails版本(grails 2.0.0)和可能更早的版本,您可以使用以下帮助器方法包装您的调用:

class BatchJob implements Job, InterruptableJob
{
  static triggers = {}

  void execute(JobExecutionContext context) {
    Batch.withSession { sess ->
      def batch = Batch.get(context.jobDetail.jobDataMap.getLongValue("batchId"))
      def foo = batch.batchStatus.description
    }
  }
}

使用最新的grails版本(grails 2.0.0)以及可能更早的版本,您可以使用以下帮助器方法包装您的调用:

class BatchJob implements Job, InterruptableJob
{
  static triggers = {}

  void execute(JobExecutionContext context) {
    Batch.withSession { sess ->
      def batch = Batch.get(context.jobDetail.jobDataMap.getLongValue("batchId"))
      def foo = batch.batchStatus.description
    }
  }
}

我认为可以调用
attach()
方法将会话添加到传递到计划作业的对象中

job.attach()

我认为可以调用
attach()
方法将会话添加到传递到计划作业的对象中

job.attach()

斯科特,谢谢你的回答。有几个问题:1)是注入了
sessionFactory
实例(即
def sessionFactory
),还是通过XMLBean配置来配置的?
sessionFactory
在传递给
getSession()
时为空;2) 我对您指定的代码使用哪些导入做了一些假设,并将它们添加到您的答案中的代码段中-您能验证它们吗?再次感谢。为了添加我的评论,我查看了SessionBinderJobListener的代码(此示例代码基于此代码),它的
sessionFactory
似乎有访问器方法。看起来您的思路是正确的。很抱歉耽搁了回来。我还没来得及重新讨论这个问题,但上次处理这个问题时,我还是遇到了一些问题。然而,我相信这些问题是由于我们使用石英的方式造成的,我相信我可以重新构建我们正在做的事情,使其正常工作。我会接受这个答案,因为我相信如果其他大多数人遇到类似的问题,它会解决他们的问题。斯科特,谢谢你的回答。有几个问题:1)是注入了
sessionFactory
实例(即
def sessionFactory
),还是通过XMLBean配置来配置的?
sessionFactory
在传递给
getSession()
时为空;2) 我对您指定的代码使用哪些导入做了一些假设,并将它们添加到您的答案中的代码段中-您能验证它们吗?再次感谢。为了添加我的评论,我查看了SessionBinderJobListener的代码(此示例代码基于此代码),它的
sessionFactory
似乎有访问器方法。看起来您的思路是正确的。很抱歉耽搁了回来。我还没来得及重新讨论这个问题,但上次处理这个问题时,我还是遇到了一些问题。然而,我相信这些问题是由于我们使用石英的方式造成的,我相信我可以重新构建我们正在做的事情,使其正常工作。我会接受这个答案,因为我相信如果其他大多数人遇到类似的问题,它会解决他们的问题。对我来说根本不起作用,但是
Batch.withTransaction{..}
Dos.withSession只提供了一种访问已绑定到线程的现有会话的简单方法。See对我来说根本不起作用,但是
Batch.withTransaction{..}
起作用。withSession只提供了一种访问已绑定到线程的现有会话的简单方法。看见
job.attach()