Граальс, как мне получить объект, чтобы НЕ сохранить - PullRequest
11 голосов
/ 26 мая 2010

Я новичок в 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 (), который вы можете использовать в приведенном выше коде. Я добавил это, но все равно безрезультатно. Я даже пытался использовать discard, а затем перезагружать клиентский объект из БД, но все еще без кубиков.

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

Ответы [ 5 ]

10 голосов
/ 26 мая 2010

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

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

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

6 голосов
/ 24 марта 2014

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

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

2 голосов
/ 19 июля 2012

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

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

0 голосов
/ 18 декабря 2015

После НИОКР я понимаю, что нам нужно очистить весь сеанс, например:

session.clear()

Согласно документации :

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

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

0 голосов
/ 21 июля 2011

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

...