Есть update action на который мы сабмитим форму редактирования объекта, например Person. Делаем валидацию которая если не прошла, возвращаемся опять в режим редактирования.
Если ошибок нет, сохраняем объект. Ну вообщем классика жанра:
def update(Long id) {
def person = Person.get(id)
person.properties = params
person.validate()
if (person.hasErrors()) {
render(view: 'edit', model: [person: person])
return
}
person.save(flush: true, failOnError: true)
}
И тут оказывается что если валидация не прошла, то сами изменения почему-то всё равно сохранились в объекте! А ведь мы точно не дёргали save().
Всё дело в dirty-checking, если вы поменяли поле в объекте то он таки уже сохранится в БД таким. К тому же на каждый action контроллера всегда открывается и флашится транзакция.
Избежать можно двумя способами: склонировать объект отдельно или заменить
get() на read(). Т.е. было:def person = Person.get(id)стало:
def person = Person.read(id)
У объекта который вернулся через
read() отключено dirty checking, и для сохранения объекта требуется явно вызвать save().Сразу же возникает вопрос, почему же тогда везде в документации используется
get()? Если вкратце то объект полученный через get() может частично обновляться только по изменённым полям, в случае с read() будет перегенериватся SQL со всеми полями. Надеюсь кому то спас несколько часов дебага :)
Комментариев нет:
Отправить комментарий