注:這裏所說的實體指的是@Entity註解的類java
繼承映射使用@Inheritance來註解,它的strategy屬性的取值由枚舉InheritanceType來定義(包含SINGLE_TABLE、TABLE_PER_CLASS、JOINED,分別相應三種繼承策略)。@Inheritance註解僅僅能做用於繼承結構的超類上。假設不指定繼承策略,默認使用SINGLE_TABLE。app
實比例如如下:ide
package com.mikan; import java.io.Serializable; import javax.persistence.Column; import javax.persistence.DiscriminatorColumn; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Inheritance; import javax.persistence.InheritanceType; import javax.persistence.Table; @Entity @Table(name = "EMP") @Inheritance(strategy = InheritanceType.SINGLE_TABLE) @DiscriminatorColumn(name = "emp_type") public class Employee implements Serializable { private static final long serialVersionUID = -7674269980281525370L; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) protected Integer empId; @Column protected String name; // getter/setter方法 } package com.mikan; import javax.persistence.Column; import javax.persistence.DiscriminatorValue; import javax.persistence.Entity; @Entity @DiscriminatorValue("FT") public class FullTimeEmployee extends Employee { private static final long serialVersionUID = 9115429216382631425L; @Column private Double salary; // getter/setter方法 } package com.mikan; import javax.persistence.Column; import javax.persistence.DiscriminatorValue; import javax.persistence.Entity; @Entity @DiscriminatorValue("PT") public class PartTimeEmployee extends Employee { private static final long serialVersionUID = -6122347374515830424L; @Column(name = "hourly_wage") private Float hourlyWage; // getter/setter方法 }當中。超類的@DiscriminatorColumn註解可以省略。默認的「discriminator列」名爲DTYPE。默認類型爲STRING。
假設指定了discriminatorType,那麼子類上@ DiscriminatorValue註解的值也應該是對應類型。
@DiscriminatorValue註解僅僅能使用在詳細的實體子類上。相同@DiscriminatorValue註解也可以省略,默認使用類名做爲值。
上面的樣例中,僅僅會生成一個表,包括了字段emp_type、empId、name、salary、hourly_wage。當保存FullTimeEmployee時,emp_type的值爲「FT」, 當保存PartTimeEmployee時。emp_type的值爲「PT」。性能
2、聯合子類策略
這樣的策略超類會被映射成一個單獨的表,每個子類也會映射成一個單獨的表。子類相應的表中僅僅包含自身屬性相應的字段,默認狀況下使用主鍵做爲超類相應的表的外鍵。url
這樣的策略對於實體間的多態關係提供了很是好的支持。spa
但缺點是實例化子類實例時需要一個或多個表的關聯操做。在深層次的繼承結構中,這會致使性能很是低。hibernate
實比例如如下:
code
package com.mikan; import java.io.Serializable; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Inheritance; import javax.persistence.InheritanceType; import javax.persistence.Table; @Entity @Table(name = "EMP") @Inheritance(strategy = InheritanceType.JOINED) public class Employee implements Serializable { private static final long serialVersionUID = -7674269980281525370L; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) protected Integer empId; @Column protected String name; // getter/setter方法 } package com.mikan; import javax.persistence.Column; import javax.persistence.DiscriminatorValue; import javax.persistence.Entity; import javax.persistence.Table; @Entity @Table(name = "FT_EMP") public class FullTimeEmployee extends Employee { private static final long serialVersionUID = 9115429216382631425L; @Column private Double salary; // getter/setter方法 } package com.mikan; import javax.persistence.Column; import javax.persistence.DiscriminatorValue; import javax.persistence.Entity; import javax.persistence.Table; @Entity @Table(name = "PT_EMP") public class PartTimeEmployee extends Employee { private static final long serialVersionUID = -6122347374515830424L; @Column(name = "hourly_wage") private Float hourlyWage; // getter/setter方法 }這會映射成三個詳細的表,各自是,Employee相應EMP表。字段包含empId、name;FullTimeEmployee相應FT_EMP表,字段包含empId、salary;PartTimeEmployee相應PT_EMP表,字段包含empId、hourly_wage。當中,表FT_EMP和PT_EMP中的empId做爲表EMP的外鍵,同是它也是主鍵。默認狀況下,使用超類的主鍵做爲子類的主鍵和外鍵。固然,可以經過@PrimaryKeyJoinColumn註解來本身指定外鍵的名稱。如FullTimeEmployee使用@PrimaryKeyJoinColumn(name = "FT_EMPID")註解。那麼該子類實體的字段爲FT_EMPID、name,FT_EMPID做爲表FT_TIME的主鍵,同一時候它也是EMP表的外鍵。
3、每個詳細的類一個表的策略
這樣的映射策略每個類都會映射成一個單獨的表,類的所有屬性。包含繼承的屬性都會映射成表的列。
這樣的映射策略的缺點是:對多態關係的支持有限,當查詢涉及到類繼承結構時一般需要發起SQL UNION查詢。實比例如如下:
blog
package com.mikan; import java.io.Serializable; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Inheritance; import javax.persistence.InheritanceType; import javax.persistence.Table; @Entity @Table(name = "EMP") @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) public class Employee implements Serializable { private static final long serialVersionUID = -7674269980281525370L; @Id @GeneratedValue(strategy = GenerationType.TABLE) protected Integer empId; @Column protected String name; // getter/setter方法 } package com.mikan; import javax.persistence.Column; import javax.persistence.DiscriminatorValue; import javax.persistence.Entity; import javax.persistence.Table; @Entity @Table(name = "FT_EMP") public class FullTimeEmployee extends Employee { private static final long serialVersionUID = 9115429216382631425L; @Column private Double salary; // getter/setter方法 } package com.mikan; import javax.persistence.Column; import javax.persistence.DiscriminatorValue; import javax.persistence.Entity; import javax.persistence.Table; @Entity @Table(name = "PT_EMP") public class PartTimeEmployee extends Employee { private static final long serialVersionUID = -6122347374515830424L; @Column(name = "hourly_wage") private Float hourlyWage; // getter/setter方法 }這會映射成三個詳細的表,各自是,Employee相應EMP表,字段包含empId、name;FullTimeEmployee相應FT_EMP表,字段包含empId、salary;PartTimeEmployee相應PT_EMP表,字段包含empId、hourly_wage。當中。表FT_EMP和PT_EMP中的empId和EMP表的empId沒有不論什麼關係。子類實體每保存一條數據,EMP表中不會插入記錄。
而且主鍵的生成策略不能使用GenerationType.AUTO或GenerationType.IDENTITY,不然會出現異常:
org.hibernate.MappingException: Cannot use identity column key generation with <union-subclass> mapping for: com.mikan.PartTimeEmployee
繼承
因爲TABLE_PER_CLASS策略每個表都是單獨的,沒有並且各表的主鍵沒有不論什麼關係,因此不能使用GenerationType.AUTO或GenerationType.IDENTITY主鍵生成策略,可以使用GenerationType.TABLE。
假設超類是抽象類。那麼不會生成相應的表。假設超類是詳細的類。那麼會生成相應的表。
以上實例使用JPA的hibernate實現測試經過。