I've created two simple Grails V3 domain classes where location is embedded attribute type in parent Venue like this
import java.time.LocalDate
class Venue {
String name
LocalDate dateCreated
LocalDate lastVisited
LocalDate lastUpdated
GeoAddress location
static hasOne = [location:GeoAddress]
static embedded =['location']
static constraints = {
lastVisited nullable:true
location nullable:true
}
static mapping = {
location cascade: "all-delete-orphan", lazy:false //eager fetch strategy
}
}
class GeoAddress {
String addressLine1
String addressLine2
String addressLine3
String town
String county
String country = "UK"
String postcode
static belongsTo = Venue
static constraints = {
addressLine1 nullable:true
addressLine2 nullable:true
addressLine3 nullable:true
town nullable:true
county nullable:true
country nullable:true
postcode nullable:true
}
}
However when I write an integration test - I found the cascade create for location didn't work (I have to save the location its no longer transient before passing to venue.
Also when I run a delete on the venue with flush:true enabled, and query for the address i still get the returned embedded address - I thought with the flush:true I'd see my GeoAddress cascade delete, but my test fails as I don't get a null when using GeoAddress.get(loc.id) as I was expecting
@Integration
@Rollback
class VenueIntegrationSpec extends Specification {
void "test venue with an address" () {
when: "create a venue and an address using transitive save on embedded "
GeoAddress address = new GeoAddress (addressLine1: "myhouse", town: "Ipswich", county: "suffolk", postcode : "IP4 2TH")
address.save() //have to save first - else Venue save fails
Venue v = new Venue (name: "bistro", location: address)
def result = v.save()
then: "retrieve venue and check its location loaded eagerly "
Venue lookupVenue = Venue.get(v.id)
GeoAddress loc = lookupVenue.location
loc.postcode == "IP4 2TH"
loc.town == "Ipswich"
when: " we delete the venue, it deletes the embedded location (Address)"
v.delete (flush:true)
GeoAddress lookupLoc = GeoAddress.get (loc.id)
then: "address should disppear"
lookupLoc == null
}
I thought I had set up this correctly but clearly I haven't. Why might my cascade actions for Venue.save() and delete() not cascade to my embedded location (GeoAddress) entry?