注:这里所说的实体指的是@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实现測试经过。