I have the following situation:
class Receipt {
BigDecimal totalAmount;
Date releaseDate;
@NotNull
Integer vatPercentage;
@NotNull
Integer discount;
Boolean isPayed;
Boolean isInvoice;
Boolean hasStampDuty;
Integer documentNumber;
@NotNull
static belongsTo = [patient:Patient, doctor:Doctor]
@NotNull
static hasMany = [healthServices:Receipt_HealthService]
static constraints = {
healthServices(blank: false)
patient(blank: false)
totalAmount(blank: false, )
vatPercentage(blank: false, nullable: false)
}
}
class HealthService {
int vat;
String description;
BigDecimal price;
static belongsTo = [healthServiceType:HealthServiceType, doctor:Doctor]
static constraints = {
healthServiceType(blank: false)
vat(size: 11..11)
description(maxSize: 255)
}
}
class Receipt_HealthService {
Receipt receipt
HealthService healthService
int quantity = 1
static constraints = {
}
}
I've manually created the Receipt_HealthService domain class, as described in the post here. Everything works well, but when I try to delete a Receipt instance, I see the following error:
Cannot delete or update a parent row: a foreign key constraint fails
(`my_localdb`.`receipt_health_service`, CONSTRAINT
`FK96DE98B9D3292D2C` FOREIGN KEY (`receipt_id`) REFERENCES `receipt`(`id`))
Why do this happen? Why the Receipt_HealthService instances are not automatically deleted? What do I need to change to allow the automatic deletion and remove the error?
The class Receipt_HealthService
doesn't have a belongsTo
, therefore Receipt
's deletions are not cascaded. See http://grails.github.io/grails-doc/latest/guide/GORM.html#cascades .
You can either change Receipt_HealthService
as following:
class Receipt_HealthService {
...
static belongsTo = [receipt: Receipt]
}
Or try to define the cascade behaviour explicitely (see http://grails.github.io/grails-doc/latest/guide/GORM.html#customCascadeBehaviour).
Another posibility is to add a beforeDelete
to Receipt
that takes care of deleting each entry in healthServices
. See http://grails.github.io/grails-doc/latest/guide/GORM.html#eventsAutoTimestamping
For this last option, you can check the classes User
, UserRole
and Role
from the Spring Security Plugin
as an example. I didn't find a sample project online, but you can just install the plugin in a sample project and run grails s2-quickstart
to see how the User#beforeDelete
looks like (see https://grails-plugins.github.io/grails-spring-security-core/ref/Scripts/s2-quickstart.html).