hibernate - Quartz 作业因 StaleObjectStateException 异常而停止执行

标签 hibernate grails exception-handling quartz-scheduler grails-2.0

我在 Grails 项目( grails 2.2.1 )上遇到了 quartz 问题(插件 :quartz2:2.1.6.2 但我什至使用插件 :quartz:1.0-RC7 也进行了测试,但问题没有改变)。

我有这样的工作

class MyJob {

def concurrent = false

def execute(context){

        try {

            //....
            // works with domains .....
            myDomain.save(flush: true)
            // works with domains .....
            //....

            sessionFactory.currentSession.flush()

        } catch (org.springframework.dao.OptimisticLockingFailureException olfe) {
            println "Job failed by database exception "
        } catch ( org.springframework.orm.hibernate3.HibernateOptimisticLockingFailureException ole){
            println "Job failed by database exception "
        } catch ( org.hibernate.HibernateException hibe ){
            println "Job failed by database exception "
        }
    }

}

}

有时在 execute 方法中会出现 StaleObjectStateException。这对我的逻辑来说没问题,我正在使用 grails 乐观锁定,并且这个异常每周只发生一次。

问题是当这个异常发生时,Job 会再次停止触发。

我曾尝试将方法代码包装在 try catch 中并在内部刷新 hibernate session 以捕获异常但没有运气。我的任何捕获都没有捕获异常。

在线查看我发现这是一个 old grails quartz bug但它已修复,在任何情况下使用 try{}catch 都必须绕过该错误。{}

附言
作业是通过这种类型的调用从 bootstrab 调度的
MyJob.schedule( 10000L )

停止调度的异常是
[194949896] core.ErrorLogger Unable to notify JobListener(s) of Job that was executed: (error will be ignored). trigger= DEFAULT.MT_3tbn6lewgiqa3 job= DEFAULT.MyJob
org.quartz.SchedulerException: JobListener 'persistenceContextJobListener' threw exception: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [MyDomain#42] [See nested exception: org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [MyDomain#42]]
    at org.quartz.core.QuartzScheduler.notifyJobListenersWasExecuted(QuartzScheduler.java:1939)
    at org.quartz.core.JobRunShell.notifyJobListenersComplete(JobRunShell.java:361)
    at org.quartz.core.JobRunShell.run(JobRunShell.java:235)
    at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:557)
Caused by: org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [MyDomain#42]
    at grails.plugin.quartz2.PersistenceContextJobListener.jobWasExecuted(PersistenceContextJobListener.groovy:46)
    at org.quartz.core.QuartzScheduler.notifyJobListenersWasExecuted(QuartzScheduler.java:1937)
    ... 3 more

.....

events.PatchedDefaultFlushEventListener Could not synchronize database state with session
org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [MyJob#42]
    at MyJob.execute(MyJob.groovy:354)
    at grails.plugin.quartz2.GrailsArtefactJob.execute(GrailsArtefactJob.java:57)
    at org.quartz.core.JobRunShell.run(JobRunShell.java:213)
    at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:557)

最佳答案

我很抱歉恢复旧帖子,但我们最近在旧版 Grails 应用程序(Grails 2.2.3)中遇到了这个问题,并且在 execute 方法中刷新 session 并不总是能解决问题,因此我将概述我们为修复该问题所做的工作问题。

在我们的例子中,有时异常会发生在 execute 方法的上下文之外,即使我们在 execute 方法中显式刷新 session 也是如此。更具体地说,异常是在 Quartz2 插件的 PersistenceContextJobListener 代码中抛出的,该代码在 execute 方法完成执行后刷新 session 。因此,在查看 Quartz2 插件代码后,我们意识到我们需要覆盖默认的 PersistenceContextJobListener 来包装作业执行方法并刷新 session 。

首先,请注意 PersistenceContextJobListener 的 jobWasExecuted 回调方法中没有异常处理。

https://github.com/9ci/grails-quartz2/blob/master/src/groovy/grails/plugin/quartz2/PersistenceContextJobListener.groovy#L44

您真正需要做的就是实现您自己的作业监听器并将 jobWasExecuted 代码包装在 try/catch 中。有关如何执行此操作的示例,请参阅以下代码片段。

https://gist.github.com/jmiranda/45084eb32f07f6e3d1934547cd4fbb9f
https://gist.github.com/jmiranda/5148f0a67afc8950bad950793e9c2303

我们以原始 Quartz 插件的 SessionBinderJobListener 为例(错误,我们或多或少复制了它)。

https://github.com/grails-plugins/grails-quartz/blob/master/src/main/groovy/grails/plugins/quartz/listeners/SessionBinderJobListener.java

无论如何,这应该使您能够防止由于未捕获的 StaleObjectStateException 而完全停止触发的作业。

关于hibernate - Quartz 作业因 StaleObjectStateException 异常而停止执行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16394437/

相关文章:

regex - 如何在JPQL中应用正则表达式?

java - Hibernate:使用命名查询时出现意外错误

ios - Grails多部分服务流意外结束

perl - 使用 Marpa::R2 实现的解析器中的异常处理

exception-handling - ASP.NET 5 分层记录异常的最佳实践

powershell - Powershell “Exit”表现不佳

java - 复制实体集合并持久保存在 Hibernate/JPA 中

java - 使用 hibernate 查询 : colon gets treated as parameter/escaping colon

grails - Grails中的Config.groovy:grails.views.default.codec-为什么选择base64?

grails - 是否有必要冲洗服务?