Grails Удалить двунаправленную связь один-к-одному - PullRequest
0 голосов
/ 18 мая 2011

У меня есть два класса домена с двунаправленной ассоциацией один к одному:

Domains

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)
   }
}

После создания Носа и Лица объектов я не могу удалить и обновить их. Когда я хочу удалить Лицо, я получаю исключение:

org.springframework.dao.DataIntegrityViolationException: внешний ключ нарушение ограничения пытается удалить teastrelation.Face с идентификатором 1 в org.grails.hbase.gorm.DeletePersistentMethod.invoke (DeletePersistentMethod.groovy: 66) в org.grails.hbase.gorm.PersistentMethod $ invoke.call (Неизвестный источник) at 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 - Невозможно получить свойство 'class' в null object java.lang.NullPointerException: не удается получить свойство 'class' на нулевой объект в 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 association.ReferenceTable - Запись справочной таблицы не найдена, строка = [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 -Не могу получить свойство 'class' в null object java.lang.NullPointerException: не удается получить свойство 'class' на нулевой объект в 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 Ответ

1 голос
/ 18 мая 2011

Я создал простое приложение для моделирования вашей проблемы. В моем примере я следовал передовым методам, а именно написал сервис для управления объектами и некоторые тесты. Как примечание, метод create на вашем Domain1Controller вызывает 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)
    }


}
...