1

動的ファインダーで古いオブジェクトの例外を一貫してスローするバッチ ジョブがあります。この仕事のために ORM ソリューションを実行しないのが理想ですが、仕方がありません。例外は、FormulaBatchPopulatorService から呼び出されている FormulaTagService で発生します。このアプリケーションは、1 つのデータベースを使用して 2 つのサーバーで実行されています。1 台のサーバーでバッチ処理を実行するだけです。

私の質問は次のとおりです。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 スニペット

   //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()
        }
4

1 に答える 1

1

あなたの答えは正しいと思います:

b) Formula.tags で行われている並べ替えがトランザクションの最後に保持されている可能性はありますか? そのため、他の誰かが別のサーバーで式を変更している場合、staleobjectexception が発生しますか?

タグをソートし、それがリストである場合、Groovy はその場でこれを行うと思います。つまり、元のリストをソートして返します。このリストは、次のいずれかの時点で永続化されます。

  1. 取引終了
  2. リクエストの終了
  3. 次に現在のセッションで DB クエリが実行されたとき (たとえば、findBy はセッションをフラッシュします)

インデックスフィールドが変更された可能性が高いため、永続化されているため、GORM / hibernate によってダーティと見なされます。

同様の問題があり、同じ問題が発生します。他の人がそれに直面していないかどうかを確認しているときに、これに出くわしました。

読み取り専用部分で何が起こっているのかわからない! あなたのサービスはトランザクショナルですか?

于 2014-08-30T20:59:26.713 に答える