LJ Dee
LJ Dee

Reputation: 87

Removing child-parent association in GORM

Consider the following domain classes

class Business{
    static hasMany = [contacts:ContactPerson]
}

class ContactPerson{
}

Given the following domain classes, say we use the following examples:

Alice is ACME's contact person. Bob and Carol are Calamity Corp's contact person.

Say I wanted to remove Bob in the ContactPerson table. Thus:

bob.delete(flush:true)

But the code will result to the server complaining about contraints:

ERROR: update or delete on table "contact_person" violates foreign key constraint
    "fk4a69c6b329ef2fe1" on table "business_contact_person"
Detail: Key (id)=(174) is still referenced from table "business_contact_person".

In this context, the exception is thrown because Bob is still associated with Calamity Corp.

How do I delete Bob from the ContactPerson table? I wanted to remove Bob from the database altogether. I don't want to add belongsTo since I don't want to cascade the delete to Business' children (that is to say, if I delete Acme Corp from the database, I still want Alice to be in the system).

I've seen examples on disassociating the parent from the child but not the other way around.

Upvotes: 3

Views: 5302

Answers (2)

LJ Dee
LJ Dee

Reputation: 87

Ok. So with a little more digging, I finally got the codes that I wanted. John Rellis' post on Relationship Advice : Grails One-To-Many was especially helpful. In this article, he mentions how to query from children to parent (which is exactly what I am looking for).

Going back to the question, I wanted to remove Bob from the ContactPerson table but given the relationship between Business and ContactPerson simply calling bob.delete() simply would not do. What I need is to look for all businesses associated with Bob and remove the association. Thus the code below:

def bob = ContactPerson.get(params.id)

def criteria = Business.createCriteria()

def businesses = criteria.listDistinct{
    createAlias("contactPersons","c")
    eq("c.id", bob.id)
}

businesses.each{business->
    business.removeFromContactPersons(bob)
    business.save(flush:true)
}

bob.delete(flush:true)

I also added a new mapping to the Business domain model:

static mapping = {
    children cascade:"all-delete-orphan"
}

Upvotes: 4

tim_yates
tim_yates

Reputation: 171084

I believe by simply adding a belongsTo, the cascade should work as expected...

class Business{
  static hasMany = [ contacts:ContactPerson ]
}

class ContactPerson{
  static belongsTo = [ business: Business ]
}

Upvotes: 4

Related Questions