Reputation: 197
In my application I have a User domain object that has a handful of fields in it including a password field. The password field is an encrypted String using JASYPT. For development purposes I am creating a new user on startup that is hard coded. It looks like this:
User user = new User(
userId:"user1", userFname:"Joe",
userLname:"Blow", userMinit:"A",
userEmail:"[email protected]", userPword:"password").save()
When the save() is called I believe that in the background the hibernate saveOrUpdate() is being called. It is comparing the new domain objects field values against already existing domain object field values to decide if the record should be inserted into the db or if it should just update an already existing record.
Since the password field is always going to be a new value because of the JASYPT encryption it is inserting a new record every time.
INSERT INTO USER VALUES(1,'[email protected]',
'Joe','user1','Blow','A','','','',
'gIkUvM9b6d5vrEhkKzqKz0U7uxqRpZFhiQrrBTDbKX0=')
INSERT INTO USER VALUES(2,'[email protected]',
'Joe','user1','Blow','A','','','',
'yap0S0mCb2CpGngcANpSWoLqlL6SozLYK4WbKYHSVEw=')
Here is the Domain class:
@Table(name="user")
class User {
String userId
String userFname
String userLname
String userMinit
String userEmail
String userPword
String userMisc1 = ""
String userMisc2 = ""
String userMisc3 = ""
public User(){};
static mapping = {
version false
columns {
userId column:'user_id'
userFname column:'user_fname'
userLname column:'user_lname'
userMinit column:'user_minit'
userEmail column:'user_email'
userPword column:'user_pword'
userMisc1 column:'user_misc1'
userMisc2 column:'user_misc2'
userMisc3 column:'user_misc3'
}
userPword type: GormEncryptedStringType
}
static constraints = {}
}
Is there a way to tell GORM to ignore the password field when saving the domain object so I don't end up with the same user over and over in the DB?
Thanks for any help.
Upvotes: 0
Views: 5243
Reputation: 535
Responding to the OPs comment, you can make properties non persistent in grails by adding a transients property to the domain class:
static transients = [ "userPword", "anotherOne" ]
But as pointed out above, this wouldn't help with your problem.
Thanks, Jim.
Upvotes: 7
Reputation: 1236
Telling GORM to ignore your password field will not solve your problem. If you create a new instance and then save it, hibernate will always try and insert this object since it knows nothing about it up to this point - it doesn't even have an id.
The only way it will do an update is if you fetch the existing record from the DB first, update attributes, then save.
Pretty much everybody goes for the solution jjczopek has suggested - check if it exists, if not create and save.
BTW, I would probably have unique constraints set on userId, userEmail for a User record - incidentally, if you do this, another way to handle your problem is to silently catch the unique constraint error that will be thrown when adding the same userId & userEmail.
Upvotes: 0
Reputation: 1683
You could override equals and hashCode, which is what Hibernate uses to determine if the object is dirty.
However, in your specific example, I think jjczopek's answer is better, as you're dealing with one special case, as opposed to behavior you desire for the entire application. Eliminating updates for password changes in the entire application would have a pretty severe impact on user management through any sort of UI.
Upvotes: 0
Reputation: 3379
Before saving new user, you can check if that user already exists:
User user = User.findByUserId("user1") ?: new User(userId:"user1", userFname:"Joe",
userLname:"Blow", userMinit:"A",
userEmail:"[email protected]",
userPword:"password").save(flush: true)
Upvotes: 4