dvisco
dvisco

Reputation: 491

Grails MongoDB Update object with Association

I can't seem to understand where I am going wrong currently when I attempt to update my User domain model that has a hasOne association to a Profile object.

My domain models are as follows:

class User {

    static hasOne = [profile: Profile]
    static fetchMode = [profile: 'eager']

    ObjectId id
    String username
}

class Profile {
   static belongsTo = [user: User]
   ObjectId id
   String familyName
   String givenName
}

I am able to persist a User with a profile originally but when attempting to update the User object I get validation errors.

Validation error occurred during call to save():
- Field error in object 'co.suitable.User' on field 'profile.familyName': rejected value [null]
- Field error in object 'co.suitable.User' on field 'profile.givenName': rejected value [null]

I am able to print out the user.profile ID and also the user.profile.familyName before saving the object. Like the following:

println(user.profile.familyName)
println(user.profile.id.toString())
user.save(flush: true, failOnError: true)

But I still get the validation errors before saving, i'd imagine that the println(user.profile.familyName) call is fetching the profile object if it already hasn't been loaded which I thought setting the fetchMode would have handled.

The object is able to successfully persist and save when I do:

user.profile = Profile.findById(user.profile.id)
println(user.profile.id.toString())
user.save(flush: true, failOnError: true)

I could wrap that in a service but I was hoping for a solution that would be handled by Grails if possible. Any advice or thoughts is much appreciated.

Upvotes: 0

Views: 323

Answers (1)

injecteer
injecteer

Reputation: 20699

You should not apply the logic for the SQL DB to Mongo 1 to 1. Mongo and other document-oriented DBs are not originally intended to store the joins between collections. There are some workarounds, like db-refs, but they are to be used with caution.

For your case - with hasOne - I would suggest using mongo's subdocuments (mirrored as GORM's embedded objects) instead of referencing:

class User {

    ObjectId id
    String username

    Profile profile
    static embedded = [ 'profile' ]

}

class Profile {
   String familyName
   String givenName
}

thus you use the mongo in accordance to it's original puprose. Also querying is simpler and faster.

Upvotes: 1

Related Questions