У меня есть пакетное задание, которое постоянно генерирует исключения устаревших объектов в динамическом поиске. В идеале я бы не использовал решение ORM для этой работы, но у меня нет выбора. Исключение возникает в FormulaTagService, который вызывается из FormulaBatchPopulatorService. Это приложение запускается на двух серверах с использованием одной базы данных. Один сервер просто выполняет пакетную обработку.
Мои вопросы: а) Почему простой оператор select, приводящий к экземпляру объекта домена, в котором не вносятся изменения в объект во время данной транзакции, в конечном итоге сохраняется в сеансе, что приводит к исключению устаревшего объекта? б) Возможно ли, что сортировка, выполняемая в 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 Фрагмент
//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()
}