實體類的要求
·實體類必須用entity標識符來聲明,或者在配制文件中指明某個類為實體類。
·實體類必須有一個無參數的構造器。它也可以有其他的構造器。這個無參數的構造器必須是public或protected的。
·如果實體實例作為一個分離對象按值傳遞(如通過一個遠程接口),則實體類必須實現serializable接口。
·實體類不允許是final的,它的所有方法都不允許是final的。
·實體支持繼承,多義關聯,多義查詢。實體類可以是抽象的,也可以是具體的。實體類可以繼承非實體類,非實體類也可以繼承實體類。
·實體的狀態由它的變量代表,這是和JavaBean的屬性一樣的。實體方法可以直接獲得變量,但是實體的客戶端必須通過獲取變量的方法(getter/setter)來獲取變量。實例變量必須是private,protected或包內可見的。
1、持久化字段和屬性
實體的狀態可以通過它的setter/getter方法或實例變量獲得,這兩種方式通稱為運行時持久化提供器(指持久化實現的運行環境,在EJB環境中,可能是EJB容器,也可能是第三方提供的集成在EJB容器內的持久化實現):
·如果聲明實體的標識符的元素值為access=FIELD,那么運行時持久化提供器直接獲取實例變量,并且持久化所有non-transient實例變量(沒有用Transient標識符標識的變量)。
·如果聲明實體的標識符的元素值為access=PROPERTY,或者沒有指定access的值,那么運行時持久化提供器通過getter/setter方法獲取實例變量,并且持久化所有non-transient實例變量(沒有用Transient標識符標識的變量)。所有的屬性獲取方法必須是public或protected。
·當使用FIELD類型時,O/R影射標識符用在變量上。當用PROPERTY時,O/R影射標識符用在getter/setter方法上。(注意:當在加載或存儲持久化狀態時,持久化提供者按照什么樣的順序來調用這些方法是不確定的。因此包含在這些方法內的業務邏輯不能依賴指定的調用順序)。
當使用持久化屬性時,要求實體遵循JavaBean的方法約定。在這種情況下,實體的類型T的每一個持久化屬性property,都有一個getter方法getProperty和一個setter方法setProperty,對于boolean值則為isProperty。
對于簡單值得持久化屬性,這些方法如下形式:
對于集合類型的字段和屬性,則必須用java.util.Collection接口定義,不管實體類是否遵循JavaBean的規范。下面的接口都是可以的:java.util.Collection,java.util.List,java.util.Set,java.util.Map。
對于集合類型的字段和屬性,類型T必須是上述集合類型中的一個。也可以使用這些集合類型的泛型變量(如:Set
為了返回和設置實例的持久化狀態,實例的屬性獲取方法內可以包含別的業務邏輯,如執行驗證。注意:當屬性的獲取類型為PROPERTY時,持久化運行環境才會執行這些業務邏輯。但在增加的業務邏輯中應該有警告信息。
在屬性獲取方法內拋出的運行時異常會引起事務回滾。當持久化運行時環境使用這些屬性獲取方法加載或存儲實例狀態時,如果拋出應用異常,則會引起持久化運行環境回滾事務,并且會拋出封裝了應用異常的PersitenceException。
實體的子類可以覆蓋它的屬性獲取方法。然而,兼容性好的應用不需要覆蓋應用在父類持久化字段和屬性上的O/R影射元數據。
實體類的持久化字段和屬性可以是原始類型、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、實體類型和/或實體類型的集合、以及嵌套類型。
O/R影射元數據可以用來客戶化O/R影射、實體狀態和實體間關系的加載和存儲。
2、創建實體實例
通過new操作符創建實體實例。當第一次創建實體實例時,這個實例是非持久化的。通過EntityManager的API可以將實例持久化。實體實例的生命周期在以后的文章中描述,在這里我就不再詳細講述了。