我有一个批处理作业,它始终在动态查找器上抛出过时的对象异常。理想情况下,我不会为这项工作运行 ORM 解决方案,但我别无选择。异常发生在从 FormulaBatchPopulatorService 调用的 FormulaTagService 中。此应用程序正在使用一个数据库的两台服务器上运行。一台服务器只执行批处理。
我的问题是:a) 为什么一个简单的 select 语句会导致在给定事务期间没有对对象进行任何更改的域对象实例最终会保留在会话中,从而导致过时的对象异常?b) 是否有可能在事务结束时保留对 formula.tags 进行的排序,从而如果其他人在不同的服务器上修改公式,则会导致 staleobjectexception?
请注意,我确实将服务更改为只读,但我仍然收到过时对象异常。任何帮助将不胜感激。
公式标签服务
@Cacheable("formulaJob")
def getFormulaByTeacherTagsOrDefaultBatchJob(Long evaluationTemplateId, List teacherTags) {
Long formulaByTagsId = existsFormulaWithSameTagsBatchJob(evaluationTemplateId, teacherTags)
if (DefaultFormulaForEvaluationTemplate.get(evaluationTemplateId) == null && formulaByTagsId ==
null) {
return null;
}
Long defaultFormulaId = DefaultFormulaForEvaluationTemplate.get(evaluationTemplateId).formulaId
return formulaByTagsId ?: defaultFormulaId
}
def existsFormulaWithSameTagsBatchJob(Long evaluationTemplateId, List tags){
// LINE BELOW THROWING STALE OBJECT EXCEPTIONS
def formulas = Formula.findAllByExtEvaluationTemplateIdAndIsActive(evaluationTemplateId, true)
for (Formula formula: formulas) {
def formulaTags = formula.tags
if (existsTagMatchIgnoringBlankTags(tags, formulaTags)) {
def id = formula.id
formula.discard()
return id
}
}
}
@CacheEvict(value='formulaJob', allEntries=true)
def resetTags(){
}
def existsTagMatchIgnoringBlankTags(List tagsToCompare, List tagsExisting) {
if (!tagsToCompare || !tagsExisting) {
return false
}
else {
return tagsToCompare?.sort() == tagsExisting?.sort()
}
}
FormulaBatchPopulatorService Snippet
//Doing this below to improve performance of batch processing
if(index%250==0){
cleanUpGorm()
formulaTagService.resetTags() //cache-evict in formulatagservice
}
def cleanUpGorm(){
def session = sessionFactory.currentSession
session.flush()
session.clear()
propertyInstanceMap.get().clear()
}