Grails(GORM)多对一级联删除行为

时间:2012-05-01 02:50:19

标签: grails gorm belongs-to cascading-deletes

我一直在努力制作正确的配置,以便在相对简单的Grails项目中产生级联删除行为。

假设我有以下简单的域类:

class Author {
    String name
    static constraints = {
    }
}

class Book {
    String title
    Author author
    static constraints = {
    }
}

如果我创建一个作者,然后创建一个由该作者编写的书,我将无法在没有先手动删除该书的情况下删除该作者。我得到了“完整性约束违规”。这并不令人惊讶,因为MySQL(我的底层数据库)是由Grails创建的,“book”表的“author”列上的“外键约束”为“Restrict”(这种行为与Grails的期望一致)我理解的文档。)

现在,如果我手动将书籍表的“作者”列上的基础数据库约束从“限制”更改为“级联”,我会得到我想要的行为。也就是说,如果您删除作者,他们的所有书籍也会被删除。

所以,我想做的是改变我的Grails“Book”类,以创建作者列上“on delete cascade”的“book”表。我一直在阅读有关做这类事情的大量信息,GORM默认使用“belongsTo”和显式“映射”。

根据“belongsTo”的文档,这样做的一种方法似乎是改变Book类中的行:

Author author

static belongsTo = [author:  Author]

从而明确表明作者是关系的“拥有方”。文档似乎表明这应该生成我之后的级联删除行为。但是,除非我在Author类中添加一个明确的“hasMany = [books:Book]”,否则它不起作用。我不想这样做。 (这个愿望在我的实际业务领域更有意义,但即使只是作为一种理解练习,我还不明白为什么我必须让作者域类明确了解书籍。)

我只是喜欢grails设置来更改Book类以在数据库中生成“cascade delete”设置,而无需更改Author类。我尝试使用如下的显式映射:

static mapping = {
        author cascade: 'all'
}

以及与其他显式映射或“belongsTo”选项的组合。这没用。

注意到对底层SQL数据库中“约束”的简单更改提供了我想要的行为,有没有办法通过Grails实现这一点?如果没有,我在这里误解了一些根本的东西,还是我想做一些愚蠢的事情?

1 个答案:

答案 0 :(得分:2)

我认为您在作者中缺少预订类型的必填字段。

以下是示例代码,根据文档(已测试并正常工作)

class Author {

    String name
    Book book //you are probably missing this field

    static constraints = {
    }
}

class Book {

    String name

    static belongsTo = [author: Author]

    static constraints = {
    }
}

测试案例

@TestFor(Author)
@Mock([Book])
class AuthorTests {

    @Test
    void testAuthorBookCascades() {

        Author a = new Author(name: "Douglas Adams")
        Book b = new Book(name: "So Long, and Thanks for all the Fish")
        a.book = b
        a.save()

        assert Author.count() == 1
        assert Book.count() == 1

        a.delete()

        assert Author.count() == 0
        assert Book.count() == 0
    }
}

如您所见,您需要作者中的Book参数。不需要hasMany或hasOne子句。