(Quick Reference)

6.2.1.1 Many-to-one and one-to-one - Reference Documentation

Authors: Graeme Rocher, Peter Ledbrook, Marc Palmer, Jeff Brown, Luke Daley, Burt Beckwith, Lari Hotari

Version: 3.0.12

6.2.1.1 Many-to-one and one-to-one

A many-to-one relationship is the simplest kind, and is defined with a property of the type of another domain class. Consider this example:

Example A

class Face {
    Nose nose
}

class Nose {
}

In this case we have a unidirectional many-to-one relationship from Face to Nose. To make this relationship bidirectional define the other side as follows (and see the section on controlling the ends of the association just below):

Example B

class Face {
    Nose nose
}

class Nose {
    static belongsTo = [face:Face]
}

In this case we use the belongsTo setting to say that Nose "belongs to" Face. The result of this is that we can create a Face, attach a Nose instance to it and when we save or delete the Face instance, GORM will save or delete the Nose. In other words, saves and deletes will cascade from Face to the associated Nose:

new Face(nose:new Nose()).save()

The example above will save both face and nose. Note that the inverse is not true and will result in an error due to a transient Face:

new Nose(face:new Face()).save() // will cause an error

Now if we delete the Face instance, the Nose will go too:

def f = Face.get(1)
f.delete() // both Face and Nose deleted

To make the relationship a true one-to-one, use the hasOne property on the owning side, e.g. Face:

Example C

class Face {
    static hasOne = [nose:Nose]
}

class Nose {
    Face face
}

Note that using this property puts the foreign key on the inverse table to the example A, so in this case the foreign key column is stored in the nose table inside a column called face_id. Also, hasOne only works with bidirectional relationships.

Finally, it's a good idea to add a unique constraint on one side of the one-to-one relationship:

class Face {
    static hasOne = [nose:Nose]

static constraints = { nose unique: true } }

class Nose {
    Face face
}

Controlling the ends of the association

Occasionally you may find yourself with domain classes that have multiple properties of the same type. They may even be self-referential, i.e. the association property has the same type as the domain class it's in. Such situations can cause problems because Grails may guess incorrectly the type of the association. Consider this simple class:

class Person {
    String name
    Person parent

static belongsTo = [ supervisor: Person ]

static constraints = { supervisor nullable: true } }

As far as Grails is concerned, the parent and supervisor properties are two directions of the same association. So when you set the parent property on a Person instance, Grails will automatically set the supervisor property on the other Person instance. This may be what you want, but if you look at the class, what we in fact have are two unidirectional relationships.

To guide Grails to the correct mapping, you can tell it that a particular association is unidirectional through the mappedBy property:

class Person {
    String name
    Person parent

static belongsTo = [ supervisor: Person ]

static mappedBy = [ supervisor: "none", parent: "none" ]

static constraints = { supervisor nullable: true } }

You can also replace "none" with any property name of the target class. And of course this works for normal domain classes too, not just self-referential ones. Nor is the mappedBy property limited to many-to-one and one-to-one associations: it also works for one-to-many and many-to-many associations as you'll see in the next section.

If you have a property called "none" on your domain class, this approach won't work currently! The "none" property will be treated as the reverse direction of the association (or the "back reference"). Fortunately, "none" is not a common domain class property name.