How to prevent from Grails not to delete child while deleting parent?

本小妞迷上赌 提交于 2020-01-15 02:47:24

问题


i have one to many relationship between author and books, one author has many books..

i have domain class like this

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



}

now when i call this function

def deleteauthor()
    {
        def id=params.id
        Author author = Author.findById(id);
        author.delete(flush: true)
        render "Author Deleted"
    }

it deletes author and all of its child books..i do not want this behaviour, i want that it cannot delete author and books and display message cannot delete author, first delete books...please tell me how to do this ?


回答1:


In your Author model you should add cascade: 'none' to constraints:

class Author {

    String authorName;
    String authorAddress;
    String authorCNIC;

    static hasMany = [books:Book]

    static mapping = {
        cascade: 'none'
    }
}

This would prevent deleting books and would just set author_id to null.

UPDATE:

It seems that setting cascade 'none' would also disable cascading saves. So one option is to manually call save on every added book instance.

Other thing I figured:

You can set cascade to only work on save-update but then when Author is delete there is constraint violation exception, because there is not way to set on delete set null on Hibernate. We could do it manually on 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)
            }
        }
   }
}

It seems to be working, although it's not very pretty.




回答2:


Due to my reputation I cannot leave a comment but I can answer. The reason it deletes the books when you delete the Author is because you have set "belongsTo" on the Author Domain. This dictates who "owns" the relationship and how cascading is handled.

You can see the following:

  • http://docs.grails.org/2.5.4/guide/GORM.html#cascades
  • http://spring.io/blog/2010/07/02/gorm-gotchas-part-2/

Specifically:

Cascading

As with other relationships, mastering collections means mastering their cascading behaviour. The first thing to note is that saves are always cascaded from the parent to its children, even if there is no belongsTo specified. If that’s the case, is there any point to using belongsTo? Yes.

Consider what happens if we execute this code in the console after we have added the author and his books:

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]

In other words, the author has been deleted, but the books haven’t. That’s where belongsTo comes in: it ensures that deletes are cascaded as well as saves. Simply by adding the line static belongsTo = Author to Book, the above code will print empty lists for Author and Book. Simple, right? In this case, yes, but the real fun is only just beginning.

Removing the belongsTo should stop cascade deletes when deleting the Author but would leave the Books behind. I think there is a way to cause an error on deletion if there are related entities but cannot right now remember how to. This would at least protect you against the cascade deletion.

I think you can add 'Author author' to Book to have the relationship still.



来源:https://stackoverflow.com/questions/41463196/how-to-prevent-from-grails-not-to-delete-child-while-deleting-parent

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!