It is critical that you understand how cascading updates and deletes work when using GORM. The key part to remember is the belongsTo setting which controls which class "owns" a relationship.

Whether it is a one-to-one, one-to-many or many-to-many, defining belongsTo will result in updates cascading from the owning class to its dependant (the other side of the relationship), and for many-/one-to-one and one-to-many relationships deletes will also cascade.

If you do not define belongsTo then no cascades will happen and you will have to manually save each object (except in the case of the one-to-many, in which case saves will cascade automatically if a new instance is in a hasMany collection).

Here is an example:

class Airport {
    String name
    static hasMany = [flights:Flight]
}

class Flight { String number static belongsTo = [airport:Airport] }

If I now create an Airport and add some Flights to it I can save the Airport and have the updates cascaded down to each flight, hence saving the whole object graph:

new Airport(name:"Gatwick")
        .addToFlights(new Flight(number:"BA3430"))
        .addToFlights(new Flight(number:"EZ0938"))
        .save()

Conversely if I later delete the Airport all Flights associated with it will also be deleted:

def airport = Airport.findByName("Gatwick")
airport.delete()

However, if I were to remove belongsTo then the above cascading deletion code would not work. To understand this better take a look at the summaries below that describe the default behaviour of GORM with regards to specific associations. Also read part 2 of the GORM Gotchas series of articles to get a deeper understanding of relationships and cascading.

Bidirectional one-to-many with belongsTo

class A { static hasMany = [bees:B] }
class B { static belongsTo = [a:A] }

In the case of a bidirectional one-to-many where the many side defines a belongsTo then the cascade strategy is set to "ALL" for the one side and "NONE" for the many side.

Unidirectional one-to-many

class A { static hasMany = [bees:B] }
class B {  }

In the case of a unidirectional one-to-many where the many side defines no belongsTo then the cascade strategy is set to "SAVE-UPDATE".

Bidirectional one-to-many, no belongsTo

class A { static hasMany = [bees:B] }
class B { A a }

In the case of a bidirectional one-to-many where the many side does not define a belongsTo then the cascade strategy is set to "SAVE-UPDATE" for the one side and "NONE" for the many side.

Unidirectional one-to-one with belongsTo

class A {  }
class B { static belongsTo = [a:A] }

In the case of a unidirectional one-to-one association that defines a belongsTo then the cascade strategy is set to "ALL" for the owning side of the relationship (A->B) and "NONE" from the side that defines the belongsTo (B->A)

Note that if you need further control over cascading behaviour, you can use the ORM DSL.