问题
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