简体   繁体   中英

Grails/GORM domain saving - transient object workaround

I found a work around to a problem I had, and I want to know if it is valid or not. It is a similar problem to: Grails Gorm : Object references an unsaved transient instance

Lets assume I have two domain Objects (names changed to protect the guilty).

public class Shelf {
    String name
    Set<Book> books = [] as Set

    static hasMany = [books: Book]
}

and

public class Book {
    String title
    Shelf shelf
}

So this means that 1 Shelf contains 0 to many Books, and one Book can be on only one Shelf.

This Shelf is very large. And at some point, it contains 80,000 Books. All stored nicely in the DB. Of course, adding new Books is getting slower and slower.

This is done by:

  Book book1 = new Book("Awesome Title")
  existingShelf.addToBooks(book1)
  existingShelf.save(flush: true)      // super slow

This is slow. Mainly (I assume) because GORM has to confirm the other 80,000 records.

So I did this to try to work around the slow point.

  Book book2 = new Book("Awesome Title 2")
  book2.save(flush: true)

This gives me an "Object references an unsaved transient instance", which I guess makes sense - the "shelf" value is empty.

So I did something a little weird:

  Book book3 = new Book("Awesome Title 3")
  book3.shelf = new Shelf()
  book3.shelf.id = <known/valid id here>
  book2.save(flush: true)

This works. It saves. There are no referential errors. Further code that depends on this... works. I just made a call that last minutes and reduced it down to seconds. But that seems too easy. I'm sure I worked around Grails magic some how. And probably broke something in the process.

Advice? Explanations?

Yes, using addTo* methods can be slow. If you look at the generated SQL you'll understand why. Doing the following:

new Book(title: "GORM Performance", shelf: grailsShelf).save()

will be faster and there is technically nothing wrong with it. Just be aware of that your instance of grailsShelf.books will not contain the new book until you've refreshed the collection from the database. This is part of what the addTo* method does for you.

Side note:

Set<Book> books = [] as Set

is unnecessary.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM