Грайлс, как мне получить объект НЕ сохранять

Я новичок в grails и пытаюсь создать форму, которая позволяет пользователю изменить адрес электронной почты, связанный с его/ее учетной записью, для сайта, который я создаю.

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

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

Смотрите код ниже:

def saveEmail =
{
    def client = ClientUser.get(session.clientUserID)
    client.email = params.email
    if(clientUserService.checkPassword(session.clientUserID , params.password) ==false)
    {
        flash.message = "Incorrect Password"
        client.discard()
        redirect(action:'changeEmail')
    }    
    else if(!client.validate())
    {
         flash.message = "Invalid Email Address"
         redirect(action:'changeEmail')
    }
    else
    {
        client.save();
        session.clientUserID = null;
        flash.message = "Your email address has been changed, please login again"
        redirect(controller: 'clientLogin' , action:'index')
    }
}

Теперь я заметил, что было странно, что если бы я ввел недействительный адрес электронной почты, он не сохранил бы изменения (как и ожидалось), но если бы я ввел неправильный пароль и действительное письмо, он сохранил бы изменения и даже написал бы их вернуться в базу данных, даже если это даст правильное сообщение об ошибке "неправильный пароль".

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

После небольшого исследования я получил документацию для метода discard(), который вы можете увидеть в приведенном выше коде. Поэтому я добавил это, но все еще не помогло. Я даже попытался использовать сброс, а затем снова перезагрузил клиентский объект из БД, но все еще не играл в кости.

Это очень неприятно, и я был бы признателен за любую помощь, так как я считаю, что это не должно быть сложным требованием!

Ответ 1

Grails закрывает сеанс Hibernate в конце веб-запроса, который очищает измененный объект. Объект, связанный с сеансом Hibernate, потому что вы овладели им через Hibernate (get()). Если вы хотите избежать сброса изменений, вам нужно использовать discard().

Это делается автоматически с помощью отказоустойчивого валидатора, поэтому вам не нужно делать это для подтверждения проверки.

Однако вы упростили бы код, переместив эту логику на специальный валидатор в один из полей ClientUser, который автоматически отбросит объект при сбое или с помощью командного объекта Grails, который также может инкапсулировать логику проверки. Затем вы просто проверяете наличие ошибок в объекте команды.

Ответ 2

Использование метода get() для получения данных в режиме чтения-записи, поэтому, если вы меняете что-либо, оно будет сохраняться. Используйте метод read(), который может извлекать данные в режиме только для чтения, поэтому, если вы меняете что-либо, тогда вам нужно использовать save(). Это решит вашу проблему.

Взгляните на это http://grails.org/doc/latest/guide/GORM.html#basicCRUD

Ответ 3

Используйте метод read, который извлекает экземпляр класса домена для указанного id в состоянии только для чтения.

Смотрите документацию Grails о чтении.

Ответ 4

Вы просто делаете flash, который не имеет ничего общего с откатом транзакции. В случае ошибки выведите RuntimeException и отбросит изменения в базе данных.

Ответ 5

После R и D я выясню, что нам нужно очистить весь сеанс, например:

session.clear()

В соответствии с документацией:

Полностью очистить сеанс. Выбросить все загруженные экземпляры и отменить все ожидающие сохранения, обновления и удаления. Не закрывать открытые итераторы или экземпляры прокручиваемых результатов.

Нам нужно правильно очистить сеанс спящего режима. В результате сеанс возвращается в пригодное для использования состояние и для будущего использования он не будет влиять на более раннюю ошибку.