Grails删除双向一对一关联

时间:2011-05-18 09:44:13

标签: grails associations gorm

我有两个具有双向一对一关联的域类:

class Nose {

  String str1

  static belongsTo = [face:Face]

}

class Face {

  String str1

  static hasOne = [nose: Nose]

}

控制器

class NoseController {
  def create() {
    nose.properties = params
    nose.save(flush: true)
  }

  def delete() {
    def nose = Nose.get(params.id as long)
    nose.delete(flush: true)
  }
}

class FaceController {

   def create() {
      def face = new Face()        
      def nose = Nose.get(params.id as long)

      if(!nose){
         face.nose = nose
         face.properties = params
         face.save(flush: true)

         nose.face = face
         nose.properties = params
         nose.save(flush:true)
      }else{
         face.properties = params
         face.save(flush: true)
      }
   }

   def delete() {
      def face = Face.get(params.id as long)
      face.delete(flush: true)
   }
}

创建 Nose Face 对象后,我无法删除更新。 当我想删除Face时,我得到例外:

  

org.springframework.dao.DataIntegrityViolationException:外键   试图删除teastrelation.Face的id为1的约束违规   org.grails.hbase.gorm.DeletePersistentMethod.invoke(DeletePersistentMethod.groovy:66)     在org.grails.hbase.gorm.PersistentMethod $ invoke.call(未知来源)     在org.grails.hbase.gorm.PersistentMethod $ invoke.call(未知来源)

要在FaceController中删除,我已更改删除操作:

def delete() {
    def face = Face.get(params.id as long)
    def nose = Nose.get(face.nose.id)

    face.nose = null
    nose.face = null
    nose.save(flush:true)
    face.save(flush:true)
    face.delete(flush: true)

    render params.id

}

并且只有在它之后我才能删除 Face 对象,但它会引发以下异常:

  

错误gorm.SavePersistentMethod - 无法在null上获取属性“class”   object java.lang.NullPointerException:无法获取属性'class'   null对象at   org.codehaus.groovy.runtime.NullObject.getProperty(NullObject.java:56)     在   org.codehaus.groovy.runtime.InvokerHelper.getProperty(InvokerHelper.java:156)     在   org.codehaus.groovy.runtime.callsite.PojoMetaClassGetPropertySite.callGetProperty(PojoMetaClassGetPropertySite.java:41)

当我想更新Face对象时,我得到以下异常:

  

ERROR associations.ReferenceTable - 找不到引用表条目,   row = [79,78,69,84,79,79,78,69,95,79,78,69,84,79,79,78,   69,95,68,79,77,65,73,78,50,95,0,0,0,0,0,0,0,1]

     

错误gorm.SavePersistentMethod - 无法在null上获取属性“class”   object java.lang.NullPointerException:无法获取属性'class'   null对象       at org.codehaus.groovy.runtime.NullObject.getProperty(NullObject.java:56)       在org.codehaus.groovy.runtime.InvokerHelper.getProperty(InvokerHelper.java:156)       在org.codehaus.groovy.runtime.callsite.PojoMetaClassGetPropertySite.callGetProperty(PojoMetaClassGetPropertySite.java:41)

我使用grails 1.3.2和hbase-0.2.4插件,我不能使用映射..

我做错了什么?

我已经花了很多时间来解决这个问题..如果有人可以的话,请帮忙。

1 个答案:

答案 0 :(得分:1)

我创建了一个简单的应用程序来模拟您的问题。在我的例子中,我遵循了最佳实践,即编写服务来管理对象和一些测试。请注意,Domain1Controller上的create方法调用save(flush:true) 3次(d1两次,d2一次),这可能不是很好,可能是你的问题。

这就是我做的事情

域名1:

package com.example

class Owner {
    String example;
    static constraints = {
        friend unique:true
    }
    static hasOne = [friend: Owned]
}

域名类2

package com.example

class Owned {

    String name;
    static constraints = {
    }
    static belongsTo = [owner: Owner]
}

管理这些域类的服务

package com.example

class OwnerService {

    static transactional = true

    def saveNewOwnerAndOwned(ownerField, ownedField){
        def owner = new Owner(example: ownedField)
        def owned = new Owned(name: ownedField)

        owner.friend = owned
        // since the relationship is bidirectional, need to set up
        // the references both ways
        owned.owner = owner

        owner.save(flush: true)
        return owner
    }

    def deleteOwner(id) {

        def toDelete = Owner.get(id)
        toDelete.delete(flush:true)

    }

    def deleteOwnedOfOwner(ownerId) {
        def owner = Owner.get(ownerId)
        def owned = owner.friend

        // must break the relationship
        owner.friend = null

        owned.delete(flush: true);
    }     
}

测试以确保其正常工作

package com.example

class OwnerServiceIntegrationTests extends GroovyTestCase {

    def ownerService
    def sessionFactory

    public void testSave(){
        def owner = ownerService.saveNewOwnerAndOwned("im an owner", "im owned");

        assertNotNull(owner)
        assertNotNull(owner.id)
        assertNotNull(owner.friend)
        assertNotNull(owner.friend.id)
    }

    public void testDelete() {

        def owner = ownerService.saveNewOwnerAndOwned("im an owner", "im owned");
        def id = owner.id
        def ownedId = owner.friend.id
        ownerService.deleteOwner(id);

        // since the integration tests hit an actual db
        // clear the session so when i start testing im sure its accurate
        def session = sessionFactory.getCurrentSession()
        session.clear()

        // make sure everything was deleted, i.e. not in db
        assertNull(Owner.get(id))
        assertNull(Owned.get(ownedId))
    }

    public void testDeleteOwned() {
        def owner = ownerService.saveNewOwnerAndOwned("im an owner", "im owned");
        def id = owner.id

        ownerService.deleteOwnedOfOwner(id);

        def session = sessionFactory.getCurrentSession()
        session.clear()

        owner = Owner.get(id)
        // make sure owner still there but friend is not
        assertNotNull(owner)
        assertNull(owner.friend)
    }


}