2010-10-01 60 views
4

我想知道從數據庫中的某一行更新域類中的單個值的最有效方法。可以說域名類有20+字段Grails:更新域中的單個對象,「.save」Vs「.executeUpdate」

def itemId = 1 

    def item = Item.get(itemId) 
    itemId.itemUsage += 1 
    Item.executeUpdate("update Item set itemUsage=(:itemUsage) where id =(:itemId)", [usageCount: itemId.itemUsage, itemId: itemId.id]) 

    vs 

    def item = Item.get(itemId) 
    itemId.itemUsage += 1 
    itemId.save(flush:true) 

回答

7

如果未更新字段的大小和數量很大(這是主觀的),則executeUpdate更有效。這也是我經常刪除實例的原因,運行'從Foo刪除id = 123',因爲我完全加載實例只是爲了調用delete(),這似乎很浪費。

如果您的域類中有大字符串並使用get()和save()方法,那麼當需要更改的所有字段都是不必要時,將所有數據從數據庫序列化到Web服務器兩次。

如果您正在使用它(如果您編輯的實例很多,您可能不應該這樣做),則需要考慮對二級緩存的影響。使用executeUpdate,它將刷新所有先前使用get()加載的實例,但是如果使用get + save更新,則只刷新一個實例。如果你是集羣化的,那麼這會變得更糟,因爲在executeUpdate之後,你將清除所有不同的集羣節點緩存,同時清除所有節點上的一個實例。

最好的選擇是基準兩種方法。如果你沒有超載數據庫,那麼你可能會過早地進行優化,並且在解決其他問題時使用標準方法可能會讓事情變得簡單。

3

我認爲他們是平等的。這兩個問題2 sql調用。

更有效的將只是一個單一的更新

Item.executeUpdate("update Item set itemUsage=itemUsage+1 where id =(:itemId)", [ itemId: itemId.id]) 
4

如果使用get/save,你會得到休眠緩存的最大優勢。 executeUpdate可能會強制更多的選擇和更新。

executeUpdate與hibernate緩存交互的方式在這裏有所不同。休眠緩存在executeUpdate上失效。該項目在executeUpdate後的下一個訪問將去數據庫(可能更多,我認爲休眠可能會使緩存中的所有項無效)。

最好的辦法是打開Config.groovy中'org.hibernate'的調試日誌並檢查SQL調用。