Grails , how do I get an object NOT to save
I am new to grails and trying to create a form which allows a user to change the email address associated with his/her account for a site I am creating.
It asks for the user for their current password and also for the new email address they want to use. If the user enters the wrong password or an invalid email address then it should reject them with an appropriate开发者_如何学Python error message.
Now the email validation can be done through constraints in grails, but the password change has to match their current password. I have implemented this check as a method on a service class.
See code below:
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')
}
}
Now what I noticed that was odd was that if I entered an invalid email then it would not save the changes (as expected) BUT if I entered the wrong password and a valid email then it would save the changes and even write them back into the database even though it would give the correct "invalid password" error message.
I was puzzled so set break points in all the if/else if/else blocks and found that it was hitting the first if statement as expected and not hitting the others , so it would never come accross a call to the save() method, yet it was saved anyway.
After a little research I came accross documentation for the discard() method which you can see used in the code above. So I added this but still no avail. I even tried using discard then reloading the client object from the DB again but still no dice.
This is very frustrating and I would be grateful for any help, since I think that this should surely not be a complicated requirement!
Grails closes your Hibernate session at the end of the web request, which will flush out the changed object. The object's connected to your Hibernate session because you got hold of it via Hibernate (get()
). If you want to avoid having the change flushed, you need to use discard()
.
This is done automatically by a failing validator, which is why you're not having to do it for a validation fail.
You'd simplify the code, however, by either moving this logic to a custom validator on one of your ClientUser
fields, which would automatically discard the object on failure, or by using a Grails command object, which could also encapsulate the verification logic. Then you'd just check for errors on the command object.
Using get() method retrieve data in read-write mode, so if you change anything it will be persist.Use read() method that can retrieve data in read-only mode so if you change anything then need to use save() method.That will resolve your problem.
Take a look at this http://grails.org/doc/latest/guide/GORM.html#basicCRUD
Use read
method that retrieves an instance of the domain class for the specified id in a read-only state.
See the Grails documentation about read.
You are just doing flash which has nothing to do with rolling back transaction. In the event of error throw RuntimeException and it will roll back your changes to the database.
After an R & D, I figure out that we need to clear a whole session like:
session.clear()
According to the documentation :
Completely clear the session. Evict all loaded instances and cancel all pending saves, updates and deletions. Do not close open iterators or instances of ScrollableResults.
We need to properly cleanup the hibernate session. In result the session is return to usable state and for future use it will not impact by the earlier error.
精彩评论