Grails 3廣泛使用特徵來混合方法,基類和工件類(域類,控制器等)的接口,並且通常行爲是相同或非常相似的,但也有一些情況像這樣在引擎蓋下的實現會影響一些事情的工作。
如果使用反編譯或反射的API,你可以看到你的域類實現多個接口這實際上是Groovy的特點,並在這裏感興趣的一個是org.grails.datastore.gorm.GormEntity
因爲它的def propertyMissing(String name)
實現的來源。這是爲了支持多個數據源,例如如果存在名爲"mongo"
的第二個數據源,則可以使用該數據源在從另一個數據源檢索到的實例上使用語法student.mongo.theMethodName(...)
進行實例方法調用。由於該方法是在特徵中定義的,因此將調用特徵方法,並忽略您的特徵。
特質可以嘗試調用你的方法,但不能保證在那裏(在這種情況下甚至不太可能,因爲這不是常用的技術),因此需要仔細的實現。
但是,您可以通過利用Groovy中的邏輯來處理該問題,以便在具有來自不同源的相同簽名的多個方法時執行該操作。從上次聲明的特徵(在類聲明中,通過implements
)的方法是被調用的方法。性狀可以呼叫super.methodname(...)
將呼叫「連鎖」到也宣佈該方法的其他特徵。
因此,從一個抽象基類更改BaseDomain
的特質:
package ...
import org.grails.datastore.gorm.GormEntity
trait DynamicProperties<D> implements GormEntity<D> {
def dynamic = [:]
def propertyMissing(String name, value) {
if (!propertyIsDatasource(name)) {
dynamic[name] = value
}
}
def propertyMissing(String name) {
if (propertyIsDatasource(name)) {
super.propertyMissing(name)
}
else {
dynamic[name]
}
}
boolean propertyIsDatasource(String name) {
false
}
}
並實現它,而不是延長:
package ...
class Student implements DynamicProperties<Student> {
String firstName
String lastName
}
可惜GormEntity
需要的類名,所以你需要冗餘包括在你的具體類中。
由於DynamicProperties
延伸GormEntity
它將在「鏈」中較早,因此它將被首先調用。
任何使用多個數據源的域類都需要用自定義邏輯覆蓋propertyIsDatasource
方法,以確保數據源名稱由GORM處理。只需在該域類中聲明相同的簽名即可。如果您知道永遠不會在任何域類中使用多個數據源,則可以刪除所有這些邏輯。
有什麼例外? –
propertyMissingException – Abdul
編輯問題以包含異常和堆棧跟蹤,使用提供的信息很難診斷 –