поток grails -> hibernateException: сессия Hibernate не связана с потоком - PullRequest
1 голос
/ 03 ноября 2010

Я пытаюсь создать несколько потоков в сервисе, но я получил hibernateException: нет сеанса .... Я уже видел обсуждение этого в stackoverflow с решением проблемы выбрасывания RuntimeException. В моем случае не работает. Вот мой сервисный код:

class MatchService {

    static transactional = true

 def void start(Match match) {

  Thread.start {
   Match updateMatch = matchSituation(match)
   if(!updateMatch.save()) {
    throw new RuntimeException("match is not valid and cannot be saved!")
   }
  }
 }

 def Match matchSituation(Match m) {
  Random random = new Random()
  if(m.teamH.averagePlayerValue > m.teamA.averagePlayerValue) {
   m.golTeamH = random.nextInt(5)
  }
  else {
   m.golTeamA = random.nextInt(4)
  }
  return m
 }
}

класс работы:

 class TestJob {

     def matchService
     List<Match> matchList = new ArrayList()

     static triggers = {
      cron name: 'trigger',  cronExpression: "0 0/1 15 ? * WED"
      }

     def group = "threadGroup"


        def execute() {
      Cal.get(1).matches.each{
       match ->
        matchList.add(match)
      }

      for(Match m: matchList) {
       if(!m.validate()) {
        throw new MatchException( message: "match not valid!!" , match:m)
       }
       matchService.start(m)

      }
        }
    }

EDIT

С плагином backgroundThread (который должен обрабатывать спящий сеанс):

    backgroundService.execute("Calculating match", {
        def backgroundMatch = match
        backgroundMatch = matchSituation(backgroundMatch)
        if(!backgroundMatch.save()) {
            throw new RuntimeException("match is not valid and cannot be saved!")
        }
    })

Я получаю эту ошибку ОШИБКА events.PatchedDefaultFlushEventListener - Не удалось синхронизировать состояние базы данных с сеансом

Ответы [ 4 ]

4 голосов
/ 03 ноября 2010

Мы используем кварцевый плагин, который отлично работает.

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

DomainClass.withTransaction {
}

Например:

def execute() {
  Cal.withTransaction {
    Cal.get(1).matches.each{
        match ->
        matchList.add(match)
    }

    for(Match m: matchList) {
        if(!m.validate()) {
            throw new MatchException( message: "match not valid!!" , match:m)
        }
        matchService.start(m)

    }
  }
}
1 голос
/ 02 января 2012

Ленивые исключения из Hibernate можно исправить, установив для fetchmode в доменном классе значение .

0 голосов
/ 04 ноября 2010

сейчас работает.Вот изменения, которые я сделал:

class TestJob {

    def matchService
    List<Match> matchList = new ArrayList()

    static triggers = {
        cron name: 'trigger',  cronExpression: "0 0/1 13 ? * THU"
    }

    def group = "threadGroup"


    def execute() {
        Cal.get(1).matches.each{ match ->
            matchList.add(match)
        }

        for(Match m: matchList) {
            if(!m.validate()) {
                throw new MatchException( message: "match not valid!!" , match:m)
            }
            matchService.run(m.id)
        }
    }
}

class MatchService {

    static transactional = true

//  Match updateMatch
    def backgroundService

    public void run(Long matchId) {

        backgroundService.execute("Calculating match", {
            def backgroundMatch = Match.findById(matchId)
            backgroundMatch = matchSituation(backgroundMatch)
            println backgroundMatch.teamH.name + " - " + backgroundMatch.teamA.name + ": " + backgroundMatch.golTeamH + " - " + backgroundMatch.golTeamA
            if(!backgroundMatch.save()) {
                throw new RuntimeException("match is not valid and cannot be saved!")
            }
        })
//      Thread.start {
//          println "run thread (" + matchId + ") : " + String.format('%tH:%<tM:%<tS.%<tL',System.currentTimeMillis())
//          this.updateMatch = matchSituation(Match.findById(matchId))
//          println updateMatch.teamH.name + " - " + updateMatch.teamA.name + ": " + updateMatch.golTeamH + " - " + updateMatch.golTeamA
//          if(!updateMatch.save(flush: true)) {
//              throw new RuntimeException("match is not valid and cannot be saved!")
//          }
//      }
    }

    def Match matchSituation(Match m) {
        Random random = new Random()
        if(m.teamH.averagePlayerValue > m.teamA.averagePlayerValue) {
            m.golTeamH = random.nextInt(5)
        }
        else {
            m.golTeamA = random.nextInt(4)
        }
        return m
    }
}
0 голосов
/ 03 ноября 2010

Я думаю, что ваша проблема в передаче фактического объекта домена в поток. Попробуйте просто передать ID объекта домена функции, а также получить и сохранить внутри этой функции / потока Передача объекта домена в другой поток может вызвать проблемы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...