Grails 的 Quartz 作业无法更新记录

Quartz job for Grails cannot update record

我的 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,用[=16=注释class,保存LeadList withNewSession,但没有任何帮助 - 同样的错误总是出现在同一行上 (list.save)

最奇怪的是这段代码以前可以工作,我不确定哪个更改会破坏它 - 在相当长的一段时间内没有提交涉及此 class 的更改。

代码是用 Grails 3.1.5 和 运行 在 Tomcat 8 上编写的。

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

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

解决方案是将对象的ID作为参数而不是整个对象发送给job,并且在job中在对数据库进行更改之前先通过ID获取对象:

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

仍然,我不知道传递整个对象之前是如何工作的,然后在某个时候突然开始导致问题。