A one-to-one relationship is the simplest kind, and is defined trivially using 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 unidirectional many-to-one relationship from Face to Nose. To make it a true one-to-one you should make nose unique:

class Face {
    Nose nose
    static constraints = {
        nose unique: true
    }
}
class Nose {
}

To make this relationship bidirectional define the other side as follows:

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 and save it and the database updates/inserts will be cascaded down to 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

Another important implication of belongsTo is that if you delete a Face instance the Nose will be deleted too:

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

In the previous example the foreign key associated the Face with the Nose is stored in the parent as column called nose_id. If you want the foreign key to be stored in the child you need a hasOne association:

Example C

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

In this example you get a bidirectional one-to-one where the foreign key column is stored in the nose table inside a column called face_id.