3

我找到了解决我遇到的问题的方法,我想知道它是否有效。这是一个类似的问题:Grails Gorm : Object references an unsaved transient instance

假设我有两个域对象(更改名称以保护有罪者)。

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

    static hasMany = [books: Book]
}

public class Book {
    String title
    Shelf shelf
}

所以这意味着 1 Shelf 包含 0 到许多 Books,而一本书只能在一个 Shelf 上。

这个架子很大。在某个时候,它包含 80,000 本书。都很好地存储在数据库中。当然,添加新书越来越慢。

这是通过以下方式完成的:

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

这很慢。主要是(我假设)因为 GORM 必须确认其他 80,000 条记录。

所以我这样做是为了尝试解决慢点。

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

这给了我一个“对象引用了一个未保存的瞬态实例”,我想这是有道理的——“架子”值是空的。

所以我做了一些有点奇怪的事情:

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

这行得通。它节省。没有参考错误。取决于此的进一步代码......有效。我只是在最后几分钟打了一个电话,然后把它缩短到几秒钟。但这似乎太容易了。我确信我在某种程度上围绕着 Grails 魔法工作。并且可能在此过程中破坏了某些东西。

建议?解释?

4

1 回答 1

5

是的,使用 addTo* 方法可能会很慢。如果您查看生成的 SQL,您就会明白为什么。执行以下操作:

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

会更快,并且在技术上没有任何问题。请注意,在您从数据库中刷新集合之前,您的 grailsS​​helf.books 实例不会包含新书。这是 addTo* 方法为您所做的一部分。

边注:

Set<Book> books = [] as Set

是不必要的。

于 2012-11-29T15:52:46.230 回答