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
Flight
s 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
Flight
s 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.