简体   繁体   English

Grails / GORM域保存 - 瞬态对象变通方法

[英]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 这是一个类似的问题: Grails Gorm:Object引用一个未保存的瞬态实例

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. 所以这意味着1个书架包含0到多本书,而一本书只能在一个书架上。

This Shelf is very large. 这个架子非常大。 And at some point, it contains 80,000 Books. 在某些时候,它包含80,000本书。 All stored nicely in the DB. 全部存储在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. 主要是(我假设),因为GORM必须确认其他80,000条记录。

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. 我敢肯定我是如何在Grails魔术周围工作的。 And probably broke something in the process. 并且可能在此过程中破坏了一些东西

Advice? 建议吗? Explanations? 解释吗?

Yes, using addTo* methods can be slow. 是的,使用addTo *方法可能会很慢。 If you look at the generated SQL you'll understand why. 如果你看一下生成的SQL,你就会明白为什么。 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. 请注意,在您从数据库刷新集合之前,您的grailsS​​helf.books实例不会包含新书。 This is part of what the addTo* method does for you. 这是addTo *方法为您所做的一部分。

Side note: 边注:

Set<Book> books = [] as Set

is unnecessary. 没必要。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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