Grails StaleObjectException с динамическим поиском (Hibernate)

У меня есть пакетное задание, которое постоянно генерирует исключения устаревших объектов в динамическом поиске. В идеале я бы не использовал решение 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()
        }

person Lior    schedule 02.06.2014    source источник


Ответы (1)


Я считаю, что ваш ответ правильный:

б) Возможно ли, что сортировка, выполняемая в Formula.tags, сохраняется в конце транзакции, что вызывает исключение staleobjectexception, если кто-то еще изменяет формулу на другом сервере?

Если вы сортируете теги и это список, я полагаю, что Groovy делает это на месте, то есть сортирует исходный список и возвращает его. Затем этот список будет сохраняться в один из следующих моментов:

  1. конец сделки
  2. конец запроса
  3. в следующий раз, когда запрос БД будет выполнен в текущем сеансе (например, findBy очистит сеанс)

Он сохраняется, поскольку поле индекса, вероятно, изменилось, поэтому GORM/hibernate считает его грязным.

У меня похожая проблема, в результате та же проблема. Я столкнулся с этим, проверяя это, чтобы увидеть, сталкивались ли с этим другие.

Не уверен, что происходит с частью только для чтения! Ваша услуга транзакционная?

person Conor Power    schedule 30.08.2014