2015-03-25 92 views
1

使用Grails 2.4.4,休眠4.3.6.1插件...Grails的級聯刪除父刪除子記錄逐一

我們必須使用與父/子一個一對多關係的域對象一個hasMany/belongsTo。刪除父記錄時,Grails將刪除級聯到子記錄。但是,在查看SQL時,我發現Grails正在提取子記錄,並使用delete ... where id = ? and version = ?

一個接一個地刪除子記錄。這是刪除子記錄的非常低效的方法,我確信Grails didn當我最初編寫這段代碼時(我找不到任何明確導致這種行爲的東西),就不要這樣做。

我希望Grails的/ Hibernate來運行一個查詢更像:

delete from Child where parent_id = ?

讓所有的孩子都記錄在刪除一個查詢,而不是成千上萬的查詢。

映射/配置中是否存在會導致Grails以這種方式運行的內容?

+0

我很確定,因爲您正在使用樂觀鎖定(例如,您沒有禁用版本)您的子實例,它必須檢查每個實例的版本,並因此一次刪除它們。這是使用GORM時的許多問題之一。 – 2015-03-25 02:36:18

+0

有趣的是,我當然可以禁用樂觀鎖定,看看它是否會改變行爲。一般來說,我認爲樂觀鎖定無論如何都是一種錯誤的安全感。 – Aaron 2015-03-25 02:39:01

+0

因此,除去從delete語句中刪除'version =?'部分,除去樂觀鎖定沒有任何影響。 – Aaron 2015-03-25 03:34:59

回答

1

很容易在事務性服務方法中顯式刪除子對象和父對象。刪除hasMany集合,並將belongsTo轉換爲常規屬性,例如

class Author { 
    String name 
} 

class Book { 
    String title 
    Author author 
} 

,然後就可以有效地刪除書籍和作者在兩個查詢:

void deleteAuthor(Author a) { 
    Book.where { author == a }.deleteAll() 
    a.delete() 
} 

關注this presentation這表明更多的原因,你應該避免使用集合。

+0

這可能是真的,但是,我仍然認爲GORM的一些變化導致了這一點。我幾乎肯定我之前對此進行了描述,並且GORM生成了通過'parent_id'刪除了孩子的SQL。 – Aaron 2015-03-25 03:33:50

+0

我在2.0.4應用程序中試過,它使用相同的N + 1方法 – 2015-03-25 03:56:37

+0

感謝您的檢查。我也做了一些測試,得出了同樣的結論。我認爲我處於一種否認狀態,即級聯算法可能在默認情況下很糟糕。 – Aaron 2015-03-25 04:28:17