2011-04-20 29 views
2

考慮下面的Grails GORM域類和使用表每個層次結構的繼承:如何從一個派生類Grails的/格姆改變域類模型對象到另一個

class Book { 
    static belongsTo = [ parent: Parent ] 
    String title 
} 

abstract class Parent { 
    static hasMany = [ books: Book ] 
} 

class A extends Parent { 
    String asset 
} 

class B extends Parent { 
    String asset 
} 

說我有獲取一個實例的A類數據庫。我想將它轉換爲B類的一個實例。什麼是grails慣用的方式來做到這一點?

如果沒有hasMany關係,我會刪除A並創建一個新的B.但是我不希望通過大量圖書並更新其parent_id字段來指向新的B的開銷。

底下,我基本上只是想執行SQL UPDATE將數據庫字段parent.class從A更改爲B.那麼在GORM/Grails中執行此操作的建議方式是什麼?

回答

1

在Grails或Hibernate中沒有這方面的支持,因爲它是將A實例更改爲B內存的類比,但是對象具有固定類型並且不能更改。沒有直接訪問鑑別器列,您需要更改值。

所以這樣做的方法是通過SQL更新,如你所說。有幾個選項,但最好的可能是groovy.sql.Sql,例如

import groovy.sql.Sql 

class FooService { 
    def dataSource 

    void convertToB(A a) { 
     def sql = new Sql(dataSource) 
     sql.executeUpdate('update parent set class=? where id=?', [B.name, a.id]) 
    } 
} 
+0

我試過本機SQL,它實際上在我的集成測試中不起作用。運行本機SQL查詢後,我仍然在檢索舊版本。我懷疑Hibernate的緩存與它有關。但是我已經開始使用一種解決方法,而不是用數據庫中的B替換A.就像你說的那樣,這實際上違背了GORM的格局,因此結果太長了。謝謝回覆! – 2011-04-21 04:46:43

1

看起來像是一個設計缺陷的跡象。

您可以嘗試用聚合替換繼承 - "Favor object composition over class inheritance." (Gang of Four 1995:20)" - 從Parent中提取一個接口,例如HasAsset,並添加對HasAsset的引用。

Groovy delegation可以提供幫助。

+0

當然,上面的例子在這裏發佈時大大簡化了,所以一些意義已經喪失。這個問題的真正目的是用一種不同類型的特定ID替換一個條目。也就是說,ID#5不再是A.現在它是B.你可以改變關於A的其他一切,爲什麼不是這個類型?但是您對Groovy代表團提出了一個非常好的建議,謝謝您的建議。 – 2011-04-21 04:34:20

+0

我明白你的意思,你看見我的了嗎?如果你想改變一切,爲什麼使用無法改變的語言元素(類繼承)?你需要的答案並不是必要的問題。我並不是說你做錯了什麼,只是指出這可能是一個糟糕決定的標誌。 – 2011-04-21 08:17:36

相關問題