Monday, May 31, 2010

Relationship Advice : Grails One-To-Many

If you are here investigating bigamy.... you have come to the wrong place.... We are actually going to have a quick once over on One-To-Many relationships in Grails and GORM (Let's abbreviate to OTM for the sake of my fingers). Here's what we'll cover:

  • Starting a Relationship
  • Living and Working With Your Relationship
  • Finding out more about your Relationship (or querying :) )
  • What if you don't belongTo someone?

Starting a Relationship :

First of all, what is an OTM? Let's let the code do the talking:

class Parent{
static hasMany = [children:Child]
String name
}

class Child {
static belongsTo = [parent:Parent]
String name
}


Here is a very simple domain model that will serve as a nice concise example. We have a Parent domain that can 'haveMany' children... in turn these children belongTo a specific parent. This is quite a 'tightly coupled' OTM. There can be a few nuances that catch people out here, which of course we will cover... (we will take a brief look at the "loosely coupled" OTM too).

The definition of the hasMany in the Parent class is actually a Map, and it should read like [collectionName:TypeContainedInCollection], so the parent has a collection with the name 'children', that will contain instances of the Child domain class.

Similarly in the Child class, the 'belongsTo' property is also a Map, [instanceOfOwningClass:typeOfOwningClass]. The 'belongsTo' property forms what I referred to earlier as a 'tightly coupled' OTM. This basically entails that the children instances are 'owned' by their 'parent', this in turn has some interesting side effects that we will cover now.

Living and Working With Your Relationship :

OK let's create a parent with some children :

def parent = new Parent(name:'Dad')

//add a new child instance
parent.addToChildren(new Child(name:'son'))

//add another child instance using a map
parent.addToChildren([name:'daughter'])

//save the parent
parent.save(flush:true,failOnError:true)

To add a Child to a Parent we use the 'addTo' method that is provided by Grails, it is basically addTo+Name of Association. When we use these methods, GORM will wire up our domain classes and because children have a 'belongsTo' property set, calling save() on the parent will also validate and save the children... sweetness :)

OK now... what if we need to remove some children from our relationship.... easy....

//retrieve our parent
def parent = Parent.findByName('Dad')

//retrieve the child instance
def child = Child.findByName('son')

//remove the child
parent.removeFromChildren(child)

parent.save()

Oh.... wait.... NOT EASY!!! If we run the above code we get the following Exception:

"not-null property references a null or transient value: Child.parent"

Yeeeeeeeeesh.... not pretty... The knee jerk reaction here might to add a nullable constraint for the parent property in the Child class... but this would be wrong. The relationship we defined has a 'belongsTo' so in this case, if we remove a child.... we simply want it to be deleted automatically at the same time. To achieve this, our Parent domain must look like:


class Parent{
static hasMany = [children:Child]
String name

static mapping = {
children cascade: "all-delete-orphan"
}
}

Now if we re-run the previous code, the child instance will be removed from our relationship and also deleted!


Finding out more about your Relationship :

If we have a Parent instance, it is rather easy to query for our children.... we simply access them as a property:

def parent = Parent.findByName(name:'Dad', [lazy:[children:false]])
parent.children.each{//do something}

However, things are not so clear cut when coming from the other direction. Suppose we have the name of a child and we want to find all the parents that have children with that name, so basically querying the relationship from the many side:

def name = 'son'

//create criteria so we can perform a criteria query
def c = Parent.createCriteria()

//perform a listDistinct as querying relationships can result in duplications
def parents = c.listDistinct{
createAlias("children", "c")
eq("c.name", name)
}

Thanks to Robert Fletcher for blogging on this (link to follow)....

What if you don't belongTo someone? :

In brief, if you define an OTM without declaring a 'belongsTo' property as we have, you're Child instances can exist on their own, without the need of being attached to a parent. One side effect of this is that the cascading save behaviour we saw before does not apply here... you will need to call save() on each domain separately.

So there we have it.... defining, creating and querying a One-To-Many relationship in Grails... I hope this has been helpful to anyone that comes across it! Happy trails!

Resources :
http://adhockery.blogspot.com/2009/06/querying-by-association-redux.html
http://www.grails.org/GORM+-+Defining+relationships

Constraining across relationships:
http://johnrellis.blogspot.com/2009/09/grails-constraints-across-relationships.html

20 comments:

  1. what if you have two parents or a grandParent? how do you define belongsto for multiple owners?

    ReplyDelete
  2. Sorry for the delay, I am unsure how to define a belongsTo for multiple parent, might be one for the user list. I know you can do, belongsTo = [MyFirstClass,MySecondClass] but I am not sure how to define it so you can have an instance as in belongsTo = [myInstance:MyClass]...

    Try the user list :)

    ReplyDelete
  3. Excellent article i am sure that i will come back here soon!

    ReplyDelete
  4. How can I capture all the validation errors occurring in the child when I call parent.save() so that I can display all the errors at once on the screen.
    e.g nameMapList.each{nameMap ->
    parent.addToChild([name:'daughter'])
    }
    parent.save(flush:true,failOnError:true)

    so now, if we loop 10 times, I need to have all the 10 errors so that I can display them on the screen at once?

    ReplyDelete
  5. Hey,

    I always thought that retrieving errors on the parent would display all those in the children that were preventing the save.

    Can you confirm in test code that this is not the case??

    John

    ReplyDelete
  6. I want to show list of all children(with all of their propertis)-short children 'list' view related to parent.How i can do this?

    ReplyDelete
  7. Thanks a lot, the steps are easy to understand and implement.

    ReplyDelete
  8. I'm gladsome to mature so more serviceable and informative assemblage on your website.
    Good Relationship With Golden Sparrow Mag

    ReplyDelete
  9. Best way to save your marriage? visit our websites just click the links.
    and find more tips about relationship.
    Visit one great deals
    Visit relationship advice

    ReplyDelete
  10. Best way to save your marriage? visit our websites just click the links.
    and find more tips about relationship.
    Visit one great deals
    Visit relationship advice

    ReplyDelete
  11. Has anything ever bothered you in life? Do you
    have any problem you need to solve? A pending
    court case you want to resolve in your favor?
    Health, relationship and finance. Welcome to
    the world of miracles and wonders, there are
    supernatural treasure and power to liberate
    mankind from all afflictions. Why cant you live a
    life of your dream? Why must you work so hard
    and yet earn so little? Why cant you be happy
    with the one you love and desire or why cant the
    one you love reciprocate and appreciate that
    love? Why would the doctor tell you there is no
    solution or cure to your problems? Why would
    your lawyer say you stand no chance, that your
    case is hopeless? Have you been cheated by
    anyone or those owing you money refuse to pay
    back? Do you need a rapid job promotion in
    your place of work? You want to venture into
    politics? Now I understand certain things are
    hard to believe and comprehend, but all I ask
    from you is only 3 days and if you will follow my
    instructions and use the items you will receive, I
    promise your life will never be the same
    again.If you find no relevance in the help I offer
    I solemnly appeals do not be vindictive and go
    in peace. And if your intentions are to take
    advantage of the powerful nature of our items
    for the purpose of evil, I will not have any
    business with you please be advised. May
    angels guide you. All inquiries should be
    directed to the Priest Abija email below Email:
    spirituallighthealing101@live.com or
    you can sent a text message to this number:(518) 303-6207!

    ReplyDelete
  12. I never ever read such type of info before this was really incredible. Discover The Cove Wine

    ReplyDelete
  13. I absolutely feel delighted once I realize articles appropriate to my work and my subject. National Retail Theft Database Articles

    ReplyDelete
  14. I am dreadfully thankful to all of your team for sharing such motivating information. Click Scuba EXPO Link

    ReplyDelete
  15. I want to give a special thanks to the prophet that helped me got
    my partner back. my name is long Steven, early this year, i
    and my wife started having some issues and she left me and the
    kids even when i loved her so much. I was frustrated to the extent
    that i started looking for links on the internet on how to get her
    back. One day i came across a testimony in which a lady was
    testifying of how this prophet helped her got her man back i was
    able to contact this prophet and helped me put everything in
    order and my wife came back to me just as i wanted. this prophet
    is great if you know you have any problem here is his email
    address prophet.drmuksolutiontemple@hotmail.com

    ReplyDelete
  16. After six years in marriage with my husband with 3 kids, he suddenly started going out with other women and coming home late, each time i confronted him it turns out to be a fight and he always threatened to divorce me at all time, my marriage was gradually coming to an end. i tried all i could to stop him from this unruly attitude but all proved abortive, until i saw a post in the forum about a spell caster who helps people cast spell on marriage and relationship problems, at first i doubted it but decided to give it a try, when i contacted this Spell caster Dr. Dangogo via email, he helped me cast a spell and within 4 hours my husband came back apologizing for all he has done and promised never to do such again and today we are happily together again. Contact this Great spell caster for your marriage or relationship issues via this email; dr.dangogospell@gmail.com

    ReplyDelete
  17. Are you worried about your marriage ? Get few sessions of our Intuitive Coaching and you can get improvement in your relation within 30 days or less. Contact for sessions!

    How do I get over my ex

    ReplyDelete
  18. Seriously awesome blog!Really great content
    Your blog is a lesson for those couples who are in critical stage of their relation!
    I know one couple who lives in my neighbour and i am seeing them fighting from the last 8 years i feel really bad for them and i wanted to help them as well !
    Therefore i am looking for such positive content loveinaclick.org/
    I will suggest your blog as well.I really wish and hope that they stop fighting !

    ReplyDelete