Я использую Grails 2.5.1, и у меня есть контроллер, вызывающий метод службы, который иногда приводит к ошибке StaleObjectStateException
. Код в сервисном методе имеет try catch вокруг вызова obj.save()
, который просто игнорирует исключение. Однако всякий раз, когда возникает один из этих конфликтов, в журнале по-прежнему печатается ошибка, и ошибка возвращается клиенту.
Мой код GameController:
def finish(String gameId) {
def model = [:]
Game game = gameService.findById(gameId)
// some other work
// this line is where the exception points to - NOT a line in GameService:
model.game = GameSummaryView.fromGame(gameService.scoreGame(game))
withFormat {
json {
render(model as JSON)
}
}
}
Мой код GameService:
Game scoreGame(Game game) {
game.rounds.each { Round round ->
// some other work
try {
scoreRound(round)
if (round.save()) {
updated = true
}
} catch (StaleObjectStateException ignore) {
// ignore and retry
}
}
}
Трассировка стека говорит, что исключение генерируется из моего метода GameController.finish
, оно не указывает ни на какой код в моем методе GameService.scoreGame
. Это означает, что Grails проверяет устаревание при запуске транзакции, а НЕ при попытке сохранения/обновления объекта?
Я сталкивался с этим исключением много раз, и обычно я исправляю его, не просматривая граф объектов.
Например, в этом случае я бы удалил ссылку game.rounds
и заменил ее на:
def rounds = Round.findAllByGameId(game.id)
rounds.each {
// ....
}
Но это означало бы, что устаревание не проверяется при создании транзакции, и это не всегда практично и, на мой взгляд, противоречит цели ленивых коллекций Grails. Если бы я хотел сам управлять всеми ассоциациями, я бы так и сделал.
Я прочитал документацию по пессимистичной и оптимистичной блокировке, но мой код следует приведенным там примерам.
Я хотел бы узнать больше о том, как/когда Grails (GORM) проверяет наличие устаревания и что с этим делать?