Cannot delete or update a parent row: a foreign key constraint in grails with mysql -
i have subscriber , contact domain , subscriber can have many contacts(one many) in grails app. when try delete data table contact throws error dbcexceptionreporter cannot delete or update parent row: foreign key constraint fails (
vprocure5.
subscriber_contact, constraint
fkc5d3af49e9f29f5foreign key (
contact_id) references
contact(
id))
.
according error message, can not delete parent row, trying delete contact data children of "subscriber" domain. here subscriber should parent , contact should child domain if not wrong.
subscriber domain
static hasmany= [contacts: contact ]
contact domain
static belongsto = [subscriber ]
contactcontroller.grooby
package com.vproc.member import org.springframework.dao.dataintegrityviolationexception class contactcontroller { def springsecurityservice def subscriberservice def imageuploadservice def searchableservice def autocompleteservice static allowedmethods = [save: "post", update: "post", delete: "post"] def index() { redirect(action: "list", params: params) } def list() { subscriber loggedinsubscriber = subscriber.get( springsecurityservice.principal.id ) list<contact>contactslist = new arraylist<contact>(); loggedinsubscriber?.contacts.each { -> contactslist.add(it) } [contactinstancelist:contactslist , contactinstancetotal: contactslist.size() ] } def create() { [contactinstance: new contact(params)] } def save() { if (params.birthday){ params.birthday = (new simpledateformat("mm/dd/yyyy")).parse(params.birthday) } def contactinstance = new contact(params) subscriber loggedinsubscriber = subscriber.get( springsecurityservice.principal.id ) if (loggedinsubscriber == null) system.out.println("not able save") else { if (!loggedinsubscriber.contacts){ loggedinsubscriber.contacts = new arraylist<contact>(); } loggedinsubscriber.contacts.add(contactinstance) if (!loggedinsubscriber.save(flush: true)) { flash.message = message(code: 'default.created.message', args: [message(code: 'contact.label', default: 'contact'), contactinstance.id]) render(view: "create", model: [contactinstance: contactinstance]) return } } flash.message = message(code: 'default.created.message', args: [message(code: 'contact.label', default: 'contact'), contactinstance.id]) redirect(action: "list") } def ajaxdelete = { def contactinstance = contact.get( params.id ); contactinstance.tags.clear(); println "==========================" if(contactinstance) { try { println "+++++++++++++++++++++++++" contactinstance.delete(flush:true) render "contact ${params.id} deleted" } catch(org.springframework.dao.dataintegrityviolationexception e) { render "contact ${params.id} not deleted" } } else { flash.message = "contact not found id ${params.id}" render(action:list) } }
contact.groovy
package com.vproc.member import java.util.date; import com.vproc.common.tag; import com.vproc.enquiry.contacttype; import grails.converters.json; class contact { string name string phonenumber string emailaddress gender gender string url string note byte[] image string address date datecreated date lastupdated contacttype contacttype date birthday static belongsto = [subscriber ] static hasmany = [tags:tag , shares: sharedcontact] static constraints = { image nullable: true phonenumber nullable: true url nullable :true address nullable :true gender nullable :true note nullable :true contacttype nullable :true birthday nullable :true } static mapping = { tags cascade: "all-delete-orphan" } //static searchable = [only: ['name', 'emailaddress']] static searchable = true static scaffold = true //static searchable = true }
subscriber.groovy
package com.vproc.member import java.util.date; class subscriber extends partyrole{ transient springsecurityservice string username string password boolean enabled boolean accountexpired boolean accountlocked boolean passwordexpired statusenum status date datecreated date lastupdated list<contact> contacts ; static belongsto = [ customer: customer] static hasmany = [scontacts: contact] static mapping = { password column: '`password`' } set<role> getauthorities() { subscriberrole.findallbysubscriber(this).collect { it.role } set } def beforeinsert() { encodepassword() } def beforeupdate() { if (isdirty('password')) { encodepassword() } } protected void encodepassword() { password = springsecurityservice.encodepassword(password) } }
any idea how can delete contact records here?
delete action in contact controller
def ajaxdelete = { subscriber loggedinsubscriber = subscriber.get( springsecurityservice.principal.id ) def contactinstance = contact.get( params.id ); contactinstance.tags.clear(); loggedinsubscriber.removefromcontacts(contactinstance) println "==========================" if(contactinstance) { try { println "+++++++++++++++++++++++++" contactinstance.delete(flush:true) render "contact ${params.id} deleted" } catch(org.springframework.dao.dataintegrityviolationexception e) { render "contact ${params.id} not deleted" } } else { flash.message = "contact not found id ${params.id}" render(action:list) } }
because you've mapped relationship this:
static belongsto = [subscriber]
grails has created join table called subscriber_contact. can see in error message:
delete or update parent row: foreign key constraint fails (vprocure5.subscriber_contact, constraintfkc5d3af49e9f29f5foreign key (contact_id) referencescontact(id))
in case, need use removefrom method on subscriber delete contact.
subscriberinstance.removefromcontacts(contactinstance)
then, gorm internally handle removing row subscriber_contact table.
optionally, should able map relationship using map notation:
static belongsto = [subscriber: subscriber]
this should negate need grails create join table , should able delete contact directly since contain fk subscriber table.
i created grails app subscriber , contact modeled way have them. wrote following test, passes:
@testfor(contact) @mock([contact, subscriber]) class contacttests { void setup() { def subscriber = new subscriber(name: 's1') def contact = new contact(name: 'c1') subscriber.addtocontacts(contact) subscriber.save() } void testdeletecontactfromsubscriber() { assertequals(contact.list().size(), 1) def dbsubscriber = subscriber.findbyname('s1') def dbcontact = contact.findbyname('c1') dbsubscriber.removefromcontacts(dbcontact) dbcontact.delete() assertequals(contact.list().size(), 0) } }
Comments
Post a Comment