0

I have the following classes:

class User {
 String name
}

class Book {
  User user
}

I want that if I delete a User object, it also deletes the Book object containing the user instance. Since I have no relation from the User class to the book class cascade delete will not work.

I can write the Book class as:

class Book {
  belongsTo = [user: User]
}

The former also does not do cascade delete because there is still no relation defined in the User class.

What I did is the following:

class User {
 String name

 def deleteUser() {
   def books = Book.findAllByUser(this)
   books.each { it.delete(flush: true) }
 }
 delete(flush: true)
}

I do not think that this is the best solution. What can I do instead? Is there a way to extend the User class delete() function somehow?

I tried the following but it fails.

 def delete() {
   def books = Book.findAllByUser(this)
   books.each { it.delete(flush: true) }
 }
 super.delete(flush: true)
Michael
  • 32,527
  • 49
  • 210
  • 370

1 Answers1

0

This is where business logic meets transactions inside of a Service class. Here is how I would do it, if I were using the relationship as you have defined it:

def UserService {

  static transactional = true

  def delete(Long userId) {
      def user = User.get(userId)
      def userBooks = Book.findAllByUser(user)
      userBooks*.delete()
      user.delete()
  }

}

And then just call this service from the controller.

Arguably, if a book really does belong to a user, define both sides of the relationship, and it should cascade.

Gregg
  • 34,973
  • 19
  • 109
  • 214
  • Would you use delete(flush:true) or without the flush? Why don't you put this method in the model? – Michael Oct 28 '13 at 17:44
  • I generally don't use flush when processing in a transaction. Especially when multiple domains are being manipulated. I don't put it in the model because I want transactional control and I'm not a big fan of that kind of business logic inside the model. – Gregg Oct 28 '13 at 17:59
  • With transactional control you mean that everything happens inside one transaction? Is this not possible in the model? – Michael Oct 28 '13 at 18:10
  • I think the Services are transactional = true per default? – Michael Oct 28 '13 at 18:10
  • I honestly don't know how transactions work within the model (Domain). I do know how they work with services which is why I suggested putting your business logic inside a service. Honestly, I think if you make the relationship bi-directional, you make your life much simpler. All you need to do then is delete the user, book deletion will cascade. If that is the behavior you are after. – Gregg Oct 28 '13 at 19:35
  • Well you are right but consider the case that the user can have 0 to 1 books and the book can contain 0 to n user. You cannot set belongsTo to the User class because the user should not be deleted when the book is deleted. Any idea for that? – Michael Oct 29 '13 at 02:26
  • Just define your relationship correctly in your Domains and let GORM handle this kind of stuff for you. What you're talking about now is a many-to-many. If you have a new question, ask a new question. Better than having conversations in comments. – Gregg Oct 29 '13 at 14:45
  • Here is the question: http://stackoverflow.com/questions/19665316/gorm-relations-without-dependent-delete – Michael Oct 29 '13 at 17:34