无法删除或更新父行:使用mysql的grails中的外键约束

Vie*_*ngh 2 mysql grails

我有订阅者和联系人域,订阅者可以在grails应用程序中拥有多个联系人(一对多).当我尝试从表联系人中删除数据时,它会抛出错误,如DBCExceptionReporter Cannot delete or update a parent row: a foreign key constraint fails (vprocure5 .subscriber_contact , CONSTRAINTFKC5D3AF49E9F29F5 FOREIGN KEY (contact_id ) REFERENCEScontact (id )).

根据错误消息,我无法删除父行,但实际上我正在尝试删除作为"订阅者"域的子项的联系人数据.如果我没有错,那么订阅者应该是父母,联系人应该是子域名.

订户域

static hasMany= [contacts: Contact ]
Run Code Online (Sandbox Code Playgroud)

联系域名

static belongsTo = [Subscriber ]
Run Code Online (Sandbox Code Playgroud)

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 { it ->
        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 to 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} could not be deleted"
        }

      }
      else {
        flash.message = "contact not found with id ${params.id}"
        render(action:list)
      }
    }
Run Code Online (Sandbox Code Playgroud)

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
}
Run Code Online (Sandbox Code Playgroud)

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 } as Set
    }

    def beforeInsert() {
        encodePassword()
    }

    def beforeUpdate() {
        if (isDirty('password')) {
            encodePassword()
        }
    }

    protected void encodePassword() {
        password = springSecurityService.encodePassword(password)
    }
}
Run Code Online (Sandbox Code Playgroud)

知道如何删除联系人记录吗?

删除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} could not be deleted"
        }

      }
      else {
        flash.message = "contact not found with id ${params.id}"
        render(action:list)
      }
    }
Run Code Online (Sandbox Code Playgroud)

Gre*_*egg 5

因为您已经映射了这样的关系:

static belongsTo = [Subscriber]
Run Code Online (Sandbox Code Playgroud)

Grails创建了一个名为subscriber_contact的连接表.您可以在错误消息中看到:

删除或更新父行,外键约束失败(vprocure5 subscriber_contact,CONSTRAINTFKC5D3AF49E9F29F5FOREIGN KEY(CONTACT_ID)REFERENCEScontact(ID))

在这种情况下,您实际上需要在订阅服务器上使用removeFrom方法来删除联系人.

subscriberInstance.removeFromContacts(contactInstance)
Run Code Online (Sandbox Code Playgroud)

然后,GORM将在内部处理从subscriber_contact表中删除行.

或者,您应该能够使用地图表示法映射您的关系:

static belongsTo = [subscriber: Subscriber]
Run Code Online (Sandbox Code Playgroud)

这应该否定了Grails创建连接表的需要,并且您应该能够直接删除联系人,因为它只包含订阅者表的FK.

我创建了一个带有订阅者和联系人的grails应用程序,就像你拥有它们一样.然后我编写了以下测试,该测试通过:

@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)
  }
}
Run Code Online (Sandbox Code Playgroud)