jonsinfinity
jonsinfinity

Reputation: 197

How to ignore field on domain object when using GORM save method

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

Answers (4)

lo_toad
lo_toad

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

Chris
Chris

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

Stevi Deter
Stevi Deter

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

jjczopek
jjczopek

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

Related Questions