實體類的要求
·實體類必須用entity標(biāo)識符來聲明,或者在配制文件中指明某個類為實體類。
·實體類必須有一個無參數(shù)的構(gòu)造器。它也可以有其他的構(gòu)造器。這個無參數(shù)的構(gòu)造器必須是public或protected的。
·如果實體實例作為一個分離對象按值傳遞(如通過一個遠(yuǎn)程接口),則實體類必須實現(xiàn)serializable接口。
·實體類不允許是final的,它的所有方法都不允許是final的。
·實體支持繼承,多義關(guān)聯(lián),多義查詢。實體類可以是抽象的,也可以是具體的。實體類可以繼承非實體類,非實體類也可以繼承實體類。
·實體的狀態(tài)由它的變量代表,這是和javabean的屬性一樣的。實體方法可以直接獲得變量,但是實體的客戶端必須通過獲取變量的方法(getter/setter)來獲取變量。實例變量必須是private,protected或包內(nèi)可見的。
1、持久化字段和屬性
實體的狀態(tài)可以通過它的setter/getter方法或?qū)嵗兞揩@得,這兩種方式通稱為運行時持久化提供器(指持久化實現(xiàn)的運行環(huán)境,在ejb環(huán)境中,可能是ejb容器,也可能是第三方提供的集成在ejb容器內(nèi)的持久化實現(xiàn)):
·如果聲明實體的標(biāo)識符的元素值為access=field,那么運行時持久化提供器直接獲取實例變量,并且持久化所有non-transient實例變量(沒有用transient標(biāo)識符標(biāo)識的變量)。
·如果聲明實體的標(biāo)識符的元素值為access=property,或者沒有指定access的值,那么運行時持久化提供器通過getter/setter方法獲取實例變量,并且持久化所有non-transient實例變量(沒有用transient標(biāo)識符標(biāo)識的變量)。所有的屬性獲取方法必須是public或protected。
·當(dāng)使用field類型時,o/r影射標(biāo)識符用在變量上。當(dāng)用property時,o/r影射標(biāo)識符用在getter/setter方法上。(注意:當(dāng)在加載或存儲持久化狀態(tài)時,持久化提供者按照什么樣的順序來調(diào)用這些方法是不確定的。因此包含在這些方法內(nèi)的業(yè)務(wù)邏輯不能依賴指定的調(diào)用順序)。
當(dāng)使用持久化屬性時,要求實體遵循javabean的方法約定。在這種情況下,實體的類型t的每一個持久化屬性property,都有一個getter方法getproperty和一個setter方法setproperty,對于boolean值則為isproperty。
對于簡單值得持久化屬性,這些方法如下形式:
對于集合類型的字段和屬性,則必須用java.util.collection接口定義,不管實體類是否遵循javabean的規(guī)范。下面的接口都是可以的:java.util.collection,java.util.list,java.util.set,java.util.map。
對于集合類型的字段和屬性,類型t必須是上述集合類型中的一個。也可以使用這些集合類型的泛型變量(如:set
為了返回和設(shè)置實例的持久化狀態(tài),實例的屬性獲取方法內(nèi)可以包含別的業(yè)務(wù)邏輯,如執(zhí)行驗證。注意:當(dāng)屬性的獲取類型為property時,持久化運行環(huán)境才會執(zhí)行這些業(yè)務(wù)邏輯。但在增加的業(yè)務(wù)邏輯中應(yīng)該有警告信息。
在屬性獲取方法內(nèi)拋出的運行時異常會引起事務(wù)回滾。當(dāng)持久化運行時環(huán)境使用這些屬性獲取方法加載或存儲實例狀態(tài)時,如果拋出應(yīng)用異常,則會引起持久化運行環(huán)境回滾事務(wù),并且會拋出封裝了應(yīng)用異常的persitenceexception。
實體的子類可以覆蓋它的屬性獲取方法。然而,兼容性好的應(yīng)用不需要覆蓋應(yīng)用在父類持久化字段和屬性上的o/r影射元數(shù)據(jù)。
實體類的持久化字段和屬性可以是原始類型、java.lang.string、也可以是其他可序列化類型(包括原始類型的封裝類型,java.math.biginteger,java.math.bigdecimal,java.util.date,java.util.calendar,java.sql.date,java.sql.time,java.sql.timestamp,用戶自定義類型,byte[],byte[],char[]和character[])、enum、實體類型和/或?qū)嶓w類型的集合、以及嵌套類型。
o/r影射元數(shù)據(jù)可以用來客戶化o/r影射、實體狀態(tài)和實體間關(guān)系的加載和存儲。
2、創(chuàng)建實體實例
通過new操作符創(chuàng)建實體實例。當(dāng)?shù)谝淮蝿?chuàng)建實體實例時,這個實例是非持久化的。通過entitymanager的api可以將實例持久化。實體實例的生命周期在以后的文章中描述,在這里我就不再詳細(xì)講述了。
3、主鍵和實體唯一標(biāo)識
每一個實體必須有一個主鍵。一個簡單主鍵(非組合主鍵)必須對應(yīng)于實體類的一個單一持久化字段或?qū)傩?。一個組合主鍵必須對應(yīng)于一個單一持久化字段或?qū)傩裕蛘邔?yīng)于一組持久化字段或?qū)傩浴<幢仨毝x一個主鍵類來代表組合主鍵。組合主鍵通常在這種情況下發(fā)生:當(dāng)從映射邏輯數(shù)據(jù)庫時,但數(shù)據(jù)庫的主鍵是由幾列組合而成的。
主鍵(字段或組合主鍵的屬性)的類型必須是:任何原始類型、任何原始類型的封裝類型、java.lang.string、java.util.date、java.sql.date。然而,通常情況下,復(fù)雜的數(shù)字類型(如float類型)不要用作主鍵。
實體類的字段和屬性都可以被主鍵類獲取。
組合主鍵需遵循以下規(guī)則:
·主鍵類必須是public的,并且有一個public的無參數(shù)構(gòu)造器。
·若access=property,則主鍵類的屬性必須是public的或protected的。
·主鍵類必須是可序列化的。
·主鍵類必須定義equals和hashcode方法。這些方法的值相等的語義必須和數(shù)據(jù)庫中字段相等的語義一致。
·組合主鍵可以是實體類的可嵌入類,也可以是實體類的多個字段或?qū)傩浴?/p>
·如果符合主鍵類對應(yīng)于實體類的多個字段或?qū)傩?,那么主鍵類的字段或?qū)傩缘拿Q必須和實體類的相應(yīng)字段或?qū)傩缘拿Q和類型一致。但是允許主鍵類和實體類采用不同的獲取類型(property或field)。
·應(yīng)用程序不能夠改變主鍵的值。規(guī)范中不定以發(fā)生改變時的處理方式,具體的實現(xiàn)可以但不要求拋出一個異常。
4、可嵌入類
實體類可以用其他類來代表實體類的狀態(tài)。這些類沒有可持久化的唯一標(biāo)識。相反,他們僅僅作為實體類實例的內(nèi)部對象。這些對象絕對是屬于他們的屬主實體類,而不會被其他實體類共享。共享這些可嵌入類會造成語義混淆,因為這些對象沒有唯一標(biāo)識符,他們和實體類實例一起才能構(gòu)成完整的數(shù)據(jù)庫映射。(在以后的版本中可能會支持嵌入類的集合、多義和繼承操作。)
可嵌入類必須遵循1.1的實體類規(guī)范,但不同的是,它不必使用entity聲明。
5、映射非關(guān)系字段或?qū)傩缘娜笔≈?/p>
如果一個可持久化字段或?qū)傩?非關(guān)系字段)沒有用第8章定義的標(biāo)識符標(biāo)識的話,則需要按順序執(zhí)行下面的規(guī)則:
·如果是一個類,而且這個類用@embeddable標(biāo)識。則被映射為@embeddable。
·如果字段或?qū)傩缘念愋褪窍旅骖愋椭械娜我庖粋€時,則被映射為@basic。類型有:原始類型、原始類型的封裝類型、java.lang.string、java.math.biginteger、java.math.bigdecimal、java.util.date、java.util.calendar、java.sql.date、java.sql.time、java.sql.timestamp、byte[]、byte[]、char[]、character[]、enums、以及任何實現(xiàn)了序列化接口的類型。
如果沒有使用標(biāo)識符,而且也沒有應(yīng)用上述規(guī)則的話,就是錯誤的。
6、實體關(guān)系
實體間的關(guān)系可以是一對一、一對多、多對一、多對多的。
如果在兩個實體間有關(guān)系,則在持久化屬性或引用實體的實例變量上必須指定關(guān)系標(biāo)識符。關(guān)系標(biāo)識符有:onetoone、onetomany、manytoone、manytomany。由于關(guān)系沒有指定目標(biāo)類型(如,java的泛型類型沒有應(yīng)用到集合類上),所以必須指定關(guān)系目標(biāo)的實體。
這些標(biāo)識符反映了在關(guān)系數(shù)據(jù)庫模型中的實際情況。使用關(guān)系模型標(biāo)識符使得與關(guān)系數(shù)據(jù)庫相關(guān)的o/r映射完全缺省,更加易于配置。這在1.1.8章節(jié)中詳細(xì)描述。
關(guān)系可以是雙向的或單向的。雙向關(guān)系既有所有方也有被屬方。單向關(guān)系只有所有邊。所有邊決定了數(shù)據(jù)庫中的更新。詳見2.2.3。
下面的規(guī)則應(yīng)用于雙向關(guān)系:
·雙向關(guān)系的反向邊必須用onetoone、onetomany或manytomany的mappedby元素指向它的所有邊。mappedby元素指明了實體的哪一個字段或?qū)傩允顷P(guān)系的擁有者。
·如果access=property,那么主鍵類的屬性必須是public或protected的。
·主鍵類必須是可序列化的。
·主鍵類必須定義equals和hashcode方法。相等的語義必須和主鍵映射到數(shù)據(jù)庫中的數(shù)據(jù)庫類型相等的語義一致。(即如果兩個對象的主鍵類相等,則它們在數(shù)據(jù)庫中就是同一條記錄)
·組合主鍵可以映射到一個嵌套類,也可以映射到實體類的多個字段。
·如果組合主鍵類被映射到實體類的多個字段或?qū)傩?,那么主鍵類的這些字段或?qū)傩缘拿趾皖愋捅仨毢蛯嶓w類是一樣的。但是,對實體類和主鍵類可以使用不同的屬性獲取類型(property或filed)。
·應(yīng)用不能改變主鍵的值??梢詫崿F(xiàn)成能改變,但不要求。如果沒有實現(xiàn),但是去修改主鍵的值時,可以拋出異常。
7、可嵌入類
實體可以使用其他的類來作為實體狀態(tài),這些類沒有持久化標(biāo)識。他們只是作為實體的嵌入對象。這些嵌入對象只屬于他們的所屬的實體,不能被其他的持久化實體共享。沒有規(guī)定如果共享這些對象會如何。因為這些對象沒有持久化標(biāo)識,所以它們通常和實體實例一起映射到數(shù)據(jù)庫中。(在這個規(guī)范的未來版本會要求支持嵌入類的集合操作,以及多態(tài)和集成)。
嵌入類除了不用entity注解聲明為實體外,必須遵守在1.1章節(jié)中對實體的所有要求。
8、映射非關(guān)系型字段或?qū)傩缘娜笔∫?guī)則
如果一個持久化字段或?qū)傩圆皇顷P(guān)系型屬性,即它不能用在第9章中定義的映射注解標(biāo)注(或者同樣的映射信息不能在xml中描述),那么將按順序使用以下缺省的映射規(guī)則:
·如果一個類用@embeddable標(biāo)識,則它被映射為@embedded。
·如果字段或?qū)傩缘念愋蛯儆谝韵骂愋椭械囊粋€時,則被映射為@basic。這些類型是:java的原始類型,原始類型的封裝類型,java.lang.string,java.math.biginteger,java.math.bigdecimal,java.util.date,java.util.calendar,java.sql.date,java.sql.time,java.sql.timestamp,byte[],byte[],char[],character[],enums,以及任何其他實現(xiàn)了序列化接口的類型。
如果沒有用注解標(biāo)注和應(yīng)用以上規(guī)則,則都是錯誤的。
新聞熱點
疑難解答
圖片精選