我在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上运行。
答案 0 :(得分:0)
我不想删除这个问题,因为解决方案可能会使某些人受益。
问题是因为作业正在接受LeadList
对象,我猜它创建了它的副本,而不是通过引用传递对象,这就是导致问题的原因。
解决方案是将对象的ID作为参数发送到作业而不是整个对象,并且在作业中首先通过ID获取对象,然后再在数据库中进行更改:
// LeadList list = context.mergedJobDataMap.get('list')
long listId = context.mergedJobDataMap.get('listId')
LeadList list = LeadList.findById(listId)
尽管如此,我还不知道如何将整个物体传递过去,然后在某个时刻突然开始引起这个问题。