Каскадное удаление без двунаправленных связей в Grails - PullRequest
3 голосов
/ 25 июля 2011

Я использую Grails 1.3.7, и у меня есть следующие классы домена:

package com.fxpal.test

class UserGroup {

    String name

    static constraints = {
        name(blank: false)
    }
}

class Invitation {

    UserGroup group
    String user

    static belongsTo = [group: UserGroup]

    static constraints = {
        group(nullable: false)
    }
}

Я хотел бы иметь возможность удалить все экземпляры Приглашения, которые ссылаются на экземпляр UserGroup, когда этот экземпляр UserGroup удален, без явного отношения, связанного с Приглашением в UserGroup. Другими словами, я хотел бы иметь каскадное удаление из группы пользователей в приглашение без изменения группы.

Мой тест для этого не пройден из-за ограничения, которое представляет отношение Приглашение -> Пользовательская группа:

void testCascadingDelete() {
    UserGroup group1 = new UserGroup(name: 'group1').save(flush: true, failOnError: true)
    UserGroup group2 = new UserGroup(name: 'group2').save(flush: true, failOnError: true)

    Invitation invitation = new Invitation(user:'user1', group: group1).save(flush: true, failOnError: true)

    assertEquals("Wrong number of groups.", 2, UserGroup.count())
    assertEquals("Wrong number of invitations.", 1, Invitation.count())

    group1.delete(flush: true, failOnError: true)

    assertEquals("Wrong number of groups.", 1, UserGroup.count())
    assertEquals("Wrong number of invitations.", 0, Invitation.count())
}

Когда я запускаю тест, он терпит неудачу так:

could not delete: [com.fxpal.test.UserGroup#1]; SQL [delete from user_group where id=? and version=?]; constraint [FK473F7799A8642225]; nested exception is org.hibernate.exception.ConstraintViolationException: could not delete: [com.fxpal.test.UserGroup#1]
org.springframework.dao.DataIntegrityViolationException: could not delete: [com.fxpal.test.UserGroup#1]; SQL [delete from user_group where id=? and version=?]; constraint [FK473F7799A8642225]; nested exception is org.hibernate.exception.ConstraintViolationException: could not delete: [com.fxpal.test.UserGroup#1]
    at com.fxpal.test.InvitationIntegrationTests.testCascadingDelete(InvitationIntegrationTests.groovy:23)
Caused by: org.hibernate.exception.ConstraintViolationException: could not delete: [com.fxpal.test.UserGroup#1]
    at com.fxpal.test.InvitationIntegrationTests.testCascadingDelete(InvitationIntegrationTests.groovy:23)
  ...

Это похоже на пример с каноническим носом, но каскадное удаление, похоже, не работает. Я действительно не хочу представлять Приглашение в Группе пользователей, в частности, потому что в конце Приглашение будет ссылаться на несколько других классов домена, удаление любого из которых также должно привести к удалению соответствующего Приглашения.

Чего мне не хватает?

Gene

1 Ответ

5 голосов
/ 25 июля 2011

Я не уверен, возможно ли это без двунаправленного отношения, но вы легко можете сделать это самостоятельно с помощью метода транзакционного обслуживания (чтобы убедиться, что все удаления происходят или не происходят):

void deleteGroup(UserGroup group) {
   Invitation.executeUpdate(
       'delete from Invitation where group=:group',
       [group: group])
   group.delete(flush: true, failOnError: true)
}

и тогда ваш тест становится

def fooService

...

void testCascadingDelete() {
    UserGroup group1 = new UserGroup(name: 'group1').save(flush: true, failOnError: true)
    UserGroup group2 = new UserGroup(name: 'group2').save(flush: true, failOnError: true)

    Invitation invitation = new Invitation(user:'user1', group: group1).save(flush: true, failOnError: true)

    assertEquals("Wrong number of groups.", 2, UserGroup.count())
    assertEquals("Wrong number of invitations.", 1, Invitation.count())

    fooService.deleteGroup group1

    assertEquals("Wrong number of groups.", 1, UserGroup.count())
    assertEquals("Wrong number of invitations.", 0, Invitation.count())
}

Пара незначительных не связанных примечаний - по умолчанию свойства не равны нулю, поэтому вы можете удалить ограничение group(nullable: false)belongsTo в форме карты, как у вас, определяет переменную с таким именем, поэтому вы можете опустить UserGroup group в Invitation.

ОБНОВЛЕНИЕ:

Еще один менее навязчивый вариант -использовать событие перед удалением в UserGroup:

def beforeDelete() {
   Invitation.executeUpdate(
      'delete from Invitation where group=:group',
      [group: this])
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...