如何防止Grails在删除父项时不删除子项?

时间:2017-01-04 11:54:38

标签: grails groovy gorm one-to-many

我在作者和书籍之间有一对多的关系,一位作者有很多书......

我有像这样的域类

Author.groovy

class Author {

    String authorName;
    String authorAddress;
    String authorCNIC;

    static hasMany = [books:Book]

    static constraints = {

        books(nullable: true)
    }
}

Book.groovy

class Book {

    String bookName;
    String Isbn;

    static belongsTo = [author:Author]

    static constraints = {

        author(nullable: true)
    }



}

现在当我调用此函数时

def deleteauthor()
    {
        def id=params.id
        Author author = Author.findById(id);
        author.delete(flush: true)
        render "Author Deleted"
    }
它删除了作者及其所有子书籍。我不想要这种行为,我希望它不能删除作者和书籍并且显示消息无法删除作者,先删除书籍...请告诉我该怎么做?

2 个答案:

答案 0 :(得分:1)

在您的作者模型中,您应该将cascade: 'none'添加到约束中:

class Author {

    String authorName;
    String authorAddress;
    String authorCNIC;

    static hasMany = [books:Book]

    static mapping = {
        cascade: 'none'
    }
}

这样可以防止删除图书,只会将author_id设置为空。

更新:

似乎设置cascade 'none'也会禁用级联保存。 因此,一个选项是在每个添加的书籍实例上手动调用save

我想到的其他事情:

您可以将级联设置为仅在save-update上工作,但是当作者删除时会出现约束违例异常,因为无法在Hibernate上设置on delete set null。我们可以在beforeDelete手动执行此操作。

class Author {

    String name;

    static hasMany = [books:Book]

    static mapping =  {
        books  cascade: 'save-update'
    }

    def beforeDelete() {
        Book.withNewSession {
            Book.findAllByAuthor(this).each {
              it.author = null
              it.save(flush: true)
            }
        }
   }
}

它似乎有效,虽然它不是很漂亮。

答案 1 :(得分:1)

由于我的声誉,我不能发表评论,但我可以回答。删除作者时删除书籍的原因是因为您在作者域上设置了“belongsTo”。这决定了谁“拥有”这种关系以及如何处理级联。

您可以看到以下内容:

具体做法是:

  

层叠

     

与其他关系一样,掌握集合意味着掌握其级联行为。首先要注意的是,即使没有指定belongsTo,保存也总是从父级子级联到子级。如果是这样的话,有没有必要使用belongsTo?是。

     

考虑一下,如果我们在添加作者及其书籍后在控制台中执行此代码会发生什么:

class Book {
  String title

  static constraints = {
    title(blank: false)
  }

}

class Author {
  String name
  Location location

  static hasMany = [ books: Book ]
}

def a = Author.get(1)
a.delete(flush: true)

println Author.list()*.name
println Book.list()*.title
The output looks like this:


[]
[Empire, Colossus]
     

换句话说,作者已被删除,但书籍却没有。这就是belongsTo的用武之地:它确保删除级联和保存。只需将静态belongsTo = Author添加到Book,上面的代码就会打印出Author和Book的空列表。简单吧?在这种情况下,是的,但真正的乐趣才刚刚开始。

删除belongsTo应该在删除作者时停止级联删除,但会将书籍留在后面。我认为有一种方法可以在删除时导致错误,如果有相关实体但现在还不能记住如何。这至少可以保护您免受级联删除。

我认为您可以将“作者作者”添加到“预订”以保持关系。