Grails的Quartz作业无法更新记录

时间:2016-07-07 16:04:56

标签: grails quartz-scheduler

我在Grails应用程序中使用了Quartz作业:

class DataWarehouseJob {

    def execute(context) {

        LeadList list = context.mergedJobDataMap.get('list')

        if (list.processing) {
            return
        }

        list.processing = true
        list.save(failOnError: true)

        ...

    }
}

list作为参数传递给作业triggerNow,并且填充了正确的值。此列表已存在于数据库中。但是,当它尝试保存列表时,会发生以下错误:

org.quartz.JobExecutionException: org.springframework.dao.DuplicateKeyException: A different object with the same identifier value was already associated with the session : [haystack.LeadList#169]; nested exception is org.hibernate.NonUniqueObjectException: A different object with the same identifier value was already associated with the session : [haystack.LeadList#169]
    at grails.plugins.quartz.GrailsJobFactory$GrailsJob.execute(GrailsJobFactory.java:111)
    at org.quartz.core.JobRunShell.run(JobRunShell.java:202)
    at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:573)
Caused by: org.springframework.dao.DuplicateKeyException: A different object with the same identifier value was already associated with the session : [haystack.LeadList#169]; nested exception is org.hibernate.NonUniqueObjectException: A different object with the same identifier value was already associated with the session : [haystack.LeadList#169]

...

Caused by: org.hibernate.NonUniqueObjectException: A different object with the same identifier value was already associated with the session : [haystack.LeadList#169]
at org.hibernate.engine.internal.StatefulPersistenceContext.checkUniqueness(StatefulPersistenceContext.java:618)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.performUpdate(DefaultSaveOrUpdateEventListener.java:301)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.entityIsDetached(DefaultSaveOrUpdateEventListener.java:244)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:109)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:90
...

我尝试添加flush: true作为保存功能的参数,在保存前调用列表上的merge,使用@ExecuteInJTATransaction注释类,保存LeadList withNewSession,但没有任何帮助 - 相同的错误总是出现在同一行(list.save

最奇怪的是,这段代码以前工作过,而且我不确定哪个更改可能会破坏它 - 在相当长的一段时间内没有任何改变提交这个类。

代码用Grails 3.1.5编写,在Tomcat 8上运行。

1 个答案:

答案 0 :(得分:0)

我不想删除这个问题,因为解决方案可能会使某些人受益。

问题是因为作业正在接受LeadList对象,我猜它创建了它的副本,而不是通过引用传递对象,这就是导致问题的原因。

解决方案是将对象的ID作为参数发送到作业而不是整个对象,并且在作业中首先通过ID获取对象,然后再在数据库中进行更改:

// LeadList list = context.mergedJobDataMap.get('list')
long listId = context.mergedJobDataMap.get('listId')
LeadList list = LeadList.findById(listId)

尽管如此,我还不知道如何将整个物体传递过去,然后在某个时刻突然开始引起这个问题。