[英]Why do scope modifiers on fields in domain classes prevent validation?
我只是從Grails(來自Rails)開始,我注意到Grails確實似乎並不喜歡域類中字段的作用域修飾符。
我了解到,默認情況下,域類中所有未作用域的字段都是public,但是如果您實際上將其聲明為public,Grails將不會對其進行驗證。
class Person {
public String firstName
public String middleName
public String lastName
}
如果添加約束,則在調用validate()時,Grails將拋出NotReadablePropertyException異常。
class Person {
public String firstName
public String middleName
public String lastName
static constraints = {
middleName nullable: true
}
}
但是,如果您刪除公共聲明,則一切正常。
有人可以通過域類的作用域解釋幕后發生的事情嗎? 很難理解為什么顯式聲明已經公開的東西會破壞框架。 我猜您也不想聲明任何“私有”,盡管如果可以將不應該直接操作的字段隱藏在域類的使用者中,那將是很好的選擇。
當您將一個字段添加到沒有范圍修飾符的Groovy類中時,更多的是推斷它是公開的,而不是實際公開的。 編譯器將字段轉換為私有字段,並為其生成一個公共的getter和setter,盡管它不會覆蓋您編寫的getter或setter。 這很方便,因為您以后可以編寫getter和/或setter來實現業務邏輯並且不影響調用方。
但是,一個公共領域(被稱為“公共”)就是一個公共領域。 沒有生成的getter或setter。 我建議使用反編譯器來查看實際效果-在src / groovy中創建一個簡單的POGO,例如
class Thing {
String realProperty
public String fieldButNotProperty
}
並使用http://jd.benow.ca/或其他反編譯器打開.class文件。
GORM會自動假定類型化屬性是持久性的,除非您在transients
列表中排除了某些屬性。 該類型是必需的,因此它知道如何持久存儲數據,並且諸如def name
類的屬性將被忽略。 從這個意義上講,屬性類似於JavaBean屬性-匹配的getter / setter對。
Hibernate不支持Groovy,也不知道幕后情況-它只是在持久化過程中調用您的getter和setter來設置和訪問字段數據。 因此,使用Groovy編譯器添加這些代碼后,Hibernate便可以輕松保留Grails中的POGO。 您可以自己執行此操作-添加具有正確名稱和數據類型(例如String getName()
和void setName(String name)
的getter和setter,即使您不使用值對它也將被視為持久屬性。 。
出現NotReadablePropertyException
的原因是,沒有getter可以調用您的“屬性”。 即使您的字段可以完全訪問,您也已對GORM和Hibernate有效地隱藏了它們。
如果添加約束,則在調用validate()時,Grails將拋出NotReadablePropertyException異常。
以前從未注意到這一點,聽起來像個bug
如果有一個不錯的選擇,那就是可以對域類的使用者隱藏不應直接操作的字段,那將是很好的選擇。
如果要防止直接訪問屬性,只需添加一個getter和setter即可。 在下面的(人為)示例中,我確保始終將名稱讀/寫為大寫字符串。
class Person {
public String firstName
public String middleName
public String lastName
public void setFirstName(String name) {
this.firstName = name.toUpperCase()
}
public String getFirstName() {
return this.firstName.toUpperCase()
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.