標籤:
轉載自:http://blog.sina.com.cn/s/blog_7085382f0100uk4p.html
基於代碼複用和模型分離的思想,在項目開發中使用JPA的@MappedSuperclass註解將實體類的多個屬性分別封裝到不同的非實體類中。
1.@MappedSuperclass註解只能標準在類上:@Target({java.lang.annotation.ElementType.TYPE})
2.標註為@MappedSuperclass的類將不是一個完整的實體類,他將不會映射到資料庫表,但是他的屬性都將映射到其子類的資料庫欄位中。
3.標註為@MappedSuperclass的類不能再標註@Entity或@Table註解,也無需實現序列化介面。
但是如果一個標註為@MappedSuperclass的類繼承了另外一個實體類或者另外一個同樣標註了@MappedSuperclass的類的話,他將可以使用@AttributeOverride或@AttributeOverrides註解重定義其父類(無論是否是實體類)的屬性對應到資料庫表中的欄位。
比如可以重定義欄位名或長度等屬性,使用@AttributeOverride中的子屬性@Column進行具體的定義。
注意:對於其父類中標註@Lob註解的屬性將不能重載,並且@AttributeOverride裡的@Column設定都將不起作用。
JPA規範中對@Lob註解並沒有說明不能同時標註@Column註解,但是在實際使用中Hibernate JPA不支援這中標註方式。
4.此外,這樣的類還可以直接標註@EntityListeners實體監聽器,他的作用範圍僅在其所有繼承類中,並且實體監聽器同樣可以保被其子類繼承或重載。
5.標註為@MappedSuperclass的類其屬性最好設定為protected或default類型的,以保證其同一個包下的子類可以直接調用它的屬性。便於實體監聽器或帶參數建構函式的操作。
6.由於標註為@MappedSuperclass的類將不是一個完整的實體類,因此其不能標註@Table,並且無法使用@UniqueConstraint設定欄位的Unique屬性,這一點以及對屬性類型重載(如重載標註為@Lob的屬性)的支援JPA規範還有待改進。
7.可以同時標註@DiscriminatorValue註解,以設定實體子類的實體識別欄位的值。該屬性一般是在實體繼承的時候使用的較多,但是在實體映射的時候可以不用設定。
8.比較實體繼承與實體映射的區別:
實體繼承的三種策略分別是:SINGLE_TABLE(所有繼承的實體都儲存在同一張資料庫表中),JOINED(每個實體子類都將儲存在一個單獨的表中),TABLE_PER_CLASS(有繼承關係的所有實體類都將儲存在單獨的表中)。
實體映射最類似於JOINED實體繼承方式,他也是將實體子類單獨儲存為一張表,但是兩者最大的區別就在於:查詢的時候JOINED使用的是多態查詢,在查詢父類時其所有實體子類的資料也將同時被查詢出,因此查詢時間和效能都將有影響。但是實體映射方式的資料庫查詢等同於沒有實體繼承關係的查詢,也就是說,他僅在實體層體現出一種繼承的關係卻並沒有在資料庫中體現這樣一種關係,他的操作都是獨立的並且將不會影響到實體子類。
Hibernate之jpa實體映射的三種繼承關係
轉載自:http://www.cnblogs.com/shangxiaofei/p/5704321.html
在JPA中,實體繼承關係的映射策略共有三種:單表繼承策略(table per class)、Joined策略(table per subclass)和Table_PER_Class策略。
1.單表繼承策略
單表繼承策略,父類實體和子類實體共用一張資料庫表,在表中通過一列辨別欄位來區別不同類別的實體。具體做法如下:
a.在父類實體的@Entity註解下添加如下的註解:
@Inheritance(Strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name=”辨別欄位列名”)
@DiscriminatorValue(父類實體辨別欄位列值)
b.在子類實體的@Entity註解下添加如下的註解:
@DiscriminatorValue(子類實體辨別欄位列值)
定義了一個父類
- @Entity
- @Inheritance(strategy = InheritanceType.SINGLE_TABLE)
- @Table(name = "WINDOW_FILE")
- @DiscriminatorColumn(name = "DISCRIMINATOR", discriminatorType = DiscriminatorType.STRING, length = 30)
- @DiscriminatorValue("WindowFile")
- public class WindowFile {
-
- @Id
- @GeneratedValue(strategy = GenerationType.AUTO)
- private Integer id;
-
- @Basic
- @Column(name = "NAME")
- private String name;
-
- @Basic
- @Column(name = "TYPE")
- private String type;
-
- @Basic
- @Column(name = "DATE")
- private Date date;
- //省略get set
- }
後定義2個子類
- @Entity
- @DiscriminatorValue("Folder")
- public class Folder extends WindowFile {
-
- @Basic
- @Column(name = "FILE_COUNT")
- private Integer fileCount;
- //省略get set
- }
- @Entity
- @DiscriminatorValue("Document")
- public class Document extends WindowFile {
-
- @Basic
- @Column(name = "SIZE")
- private String size;
- //省略get set
- }
以上通過列DISCRIMINATOR的不同,區分具體父子實體。
實際表結構如下:
WINDOW_FILE DISCRIMINATOR,ID,NAME,DATE,TYPE,SIZE,FILE_COUNT
當你使用WindowFile實體時,實際表的欄位為DISCRIMINATOR=‘WindowFile‘,SIZE與FILE_COUNT永遠是空
當使用Folder實體時,DISCRIMINATOR=‘Folder‘,SIZE永遠是空,FILE_COUNT為實際值。
Document同理,與Folder類似。
2.Joined策略
父類實體和子類實體分別對應資料庫中不同的表,子類實體的表中只存在其擴充的特殊屬性,父類的公用屬性儲存在父類實體映射表中。具體做法:
@Inheritance(Strategy=InheritanceType.JOINED)
子類實體不需要特殊說明。
- @Entity
- @Table(name = "T_ANIMAL")
- @Inheritance(strategy = InheritanceType.JOINED)
- public class Animal {
-
- @Id
- @Column(name = "ID")
- @GeneratedValue(strategy = GenerationType.AUTO)
- private Integer id;
-
- @Column(name = "NAME")
- private String name;
-
- @Column(name = "COLOR")
- private String color;
- //省略get set
- }
- @Entity
- @Table(name = "T_BIRD")
- @PrimaryKeyJoinColumn(name = "BIRD_ID")
- public class Bird extends Animal {
-
- @Column(name = "SPEED")
- private String speed;
- //省略get set
- }
- @Entity
- @Table(name = "T_DOG")
- @PrimaryKeyJoinColumn(name = "DOG_ID")
- public class Dog extends Animal {
-
- @Column(name = "LEGS")
- private Integer legs;
- //省略get set
- }
實際表結構如下:
T_ANIMAL ID,COLOR,NAME
T_BIRD SPEED,BIRD(既是外鍵,也是主鍵)
T_DOG LEGS,DOG_ID(既是外鍵,也是主鍵)
3.Table_PER_Class策略:
Table_PER_Class策略,父類實體和子類實體每個類分別對應一張資料庫中的表,子類表中儲存所有屬性,包括從父類實體中繼承的屬性。具體做法:
只需在父類實體的@Entity註解下添加如下註解:
@Inheritance(Strategy=InheritanceType.TABLE_PER_CLASS)
- @Entity
- @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
- @Table(name = "T_VEHICLE")
- public class Vehicle { // 基類
-
- @Id
- // @GeneratedValue
- @Column(name = "ID")
- private Integer id;
-
- @Column(name = "SPEED")
- private Integer speed;// 速度
- //省略get set
- }
- @Entity
- @Table(name = "T_CAR")
- public class Car extends Vehicle {
-
- @Column(name = "ENGINE")
- private String engine;// 發動機
- //省略get set
- }
一旦使用這種策略就意味著你不能使用AUTO generator 和IDENTITY generator,即主索引值不能採用資料庫自動產生。
實際表結構如下:
T_VEHICLE ID,SPEED
T_CAR ID,SPEED,ENGINE
@MappedSuperclass註解的使用說明