2012-11-29 30 views
3

我找到了解決問題的方法,並且我想知道它是否有效。這是一個類似的問題:Grails Gorm : Object references an unsaved transient instance保存Grails/GORM域名 - 瞬態對象解決方法

讓我們假設我有兩個域對象(名稱更改爲保護有罪)。

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

    static hasMany = [books: Book] 
} 

public class Book { 
    String title 
    Shelf shelf 
} 

因此,這意味着1架包含0到很多書籍,和一本書可以在只有一個貨架。

這個架子非常大。並且在某個時候它包含80,000本書。所有存儲在數據庫中很好。當然,添加新書越來越慢。

這是通過:

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

這是緩慢的。主要(我假設)是因爲GORM必須確認其他8萬條記錄。

所以我這樣做是爲了解決這個問題。

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的魔術中工作過一些。可能在這個過程中破壞了一些東西。

建議?解釋嗎?

+1

您是否已經測試過'Book book4 = new Book(標題:「Awesome Title 4」,shelf:existingShelf)的性能? – rdmueller

回答

5

是的,使用addTo *方法可能會很慢。如果你看看生成的SQL,你會明白爲什麼。執行以下操作:

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

會更快,並且在技術上沒有問題。請注意,在您從數據庫刷新集合之前,您的grailsS​​helf.books實例將不包含新書。這是addTo *方法爲你做的一部分。

旁註:

Set<Book> books = [] as Set 

是不必要的。

+0

在適用於我的情況的示例中,grailsS​​helf僅存在於方法的範圍內。它沒有被傳遞,所以我不認爲這會是一個問題。當使用貨架對象時,它被「重新收集」。 是的,SQL語句是相當可觀的:) – winna

+0

我基本上實現了你所說的,但在一個「醜陋」的方式。感謝您確認我做了什麼。 – winna

相關問題