2011年6月24日 星期五

SCEA - Advanced Persistence Concepts

Inheritance
為了要能正確的使用ORM,有以下幾種策略模式,
  • Single table per class hierarchy.

  • Separate table per subclass.

  • Single table per concrete entity class.
先從Single table per class hierarchy這個策略模式來看,顧名思義就是要用單一一個class來表達完整的物件結構內容,所以只要有subclass的也就都存放在這個表當中,為了能有效區別出到底資料表示哪一種格式(java type),會需要一個discriminator key(需要在資料表中真的開這樣的一個欄位)來做區別,這種策略模式的好處是很有效率( 查詢、更新、刪除等等),同時也很便利的支援了物件轉型(多型的使用),而當然也是有壞處的,像是必須存放所有任何子類別會有可能用到的欄位,得通通放上來,變成一個很龐大的怪物。

Separate table per subclasses,將各個子類別獨立出來存放,參考的annotation如下。


這個策略模式,其實就是將主要的main table視為parent class,而對於每個subclass都須持有一個FK from 父類別。很有趣的是,如果沒有設置@Table的話,container就會預設將class name 當成 table name,對於命名規則不同的情況下要特別留意。在分散子類別的策略模式中,在主要的root table 仍然得保有discriminator key,用來識別其形態,藉此了解那些欄位會有值,那些欄位不會有值。

Single Table per concrete Entity class,在這種策略模式下,每個子類別皆有其各自的資料表,每個資料表都會存放有所有的欄位內容(也就是說子類別會包含有父類別的欄位),像這種處理方式就不支援多型了。

Other Modes of Inheritance
以下這些規則是Entities的繼承體系原則:



  • Entities can extend non-entity classes

  • Non-entity classes can extend entity classes

  • Abstract classes can be entities

  • An entity class can inherit from another entity class

為了要能使用任意一個entity class去繼承 non-entitiy class,需要加註@MappedSuperclass ,被繼承的父類別其實本身並沒有包含任何db table 欄位資訊,這種的設計方式通常是為了提供一個共通類的資料內涵,但是對於一些更細的細節尚未定義,想留在後續的開發中才補上相關設計內容,於是就出現了這樣的設計原則,或許也跟Abstract class有點異曲同工之妙,以下是簡單的範例參考。



Polymorphism
基本上多型的用法就跟java的用法一樣,而在JPA的使用上則是以查詢語法作呈現,像是下面這樣用:

Query q = em.createQuery( "select r from RoadVehicle r " );

系統查詢時,會將所有符合 RoadVehicle 型別的結果通通都抓回來。

Relationships

  • One-to-one

  • One-to-many

  • Many-to-one

  • Many-to-many

先看到one-to-one的部分,一般的狀況下這種關係對應都是透過foreign key來達成,參考下圖。


在一對一的資料關聯情況下,假設被對應的FK一定得有值,通常會以組合物件的方式來確保,看一下下面的案例:


//在class Order中的method


// ShipmentUni , 每個訂單都要有他送貨的地點資料


在上述的案例中,每個訂單都有其送貨資訊,採1-1的關聯方式,並設置了cascading,確保當有訂單時,就一定得有送貨地點。

來看個一對多的案例,雖然好像我經手過的案子沒有真的這樣做,但看看標準案例也不賴。在面臨一對多的案例時,要善用Lazy-initializnation -->FetchType.LAZY,如此可避免一次載入大量資料,造成memory 濫用問題。

正確的一對多做法,是要透過一個join table,來分別闡述一對多的兩個不同表如下:


對於FetchType.LAZY的相反作法是 FetchType.EAGER,這表示是無論如何都直接載入,當然它可以搭配另一個屬性mappedBy來做設定,像是 mappedBy="company",實作的範例就直接看pdf了。Many to many 也參照pdf:D

EJB-QL Enhancements

沒有留言: