因为关系数据库的表之间不存在继承关系,Entity 提供三种基本的继承映射策略:
每个类分层结构一张表(table per class hierarchy)
每个子类一张表(table per subclass)
每个具体类一张表(table per concrete class)
一、每个类分层结构一张表(table per class hierarchy)
          这种映射方式只需为基类创建一个表即可。在表中不仅提供基类所有属性对应的字段,还要提供所有子类属性对应的字段,此外还需要一个字段用于区分子类的具体类型
          要使用每个类分层结构一张表(table per class hierarchy) 策略,需要把@javax.persistence.Inheritance 注释的strategy属性设置为InheritanceType.SINGLE_TABLE。除非你要改变子类的映射策略,否则@Inheritance 注释只能放在继承层次的基类。通过鉴别字段的值,持久化引掣可以区分出各个类,并且知道每个类对应那些字段。鉴别字段通过@javax.persistence.DiscriminatorColumn 注释进行定义,name 属性定义鉴别字段的列名,discriminatorType 属性定义鉴别字段的类型(可选值有:String, Char, Integer),如果鉴别字段的类型为String 或Char,可以用length 属性定义其长度。@DiscriminatorValue 注释为继承关系中的每个类定义鉴别值,如果不指定鉴别值,默认采用类名
例:
       @SuppressWarnings("serial")
       @Entity
       @Table(name="Vehicle_Hierarchy")
       @Inheritance(strategy=InheritanceType.SINGLE_TABLE)
       @DiscriminatorColumn(name="Discriminator",
                                            discriminatorType = DiscriminatorType.STRING,
                                            length=30)
       @DiscriminatorValue("Vehicle")
       public class Vehicle implements Serializable{       //基类
       private Long id;
       private Short speed;//速度
       @Id
       @GeneratedValue
       @Column(columnDefinition="integer")//指定使用适配Integer长度的数据类型
       public Long getId() {
       return id;
       }
       public void setId(Long id) {
       this.id = id;
       }
      @SuppressWarnings("serial")
      @Entity
      @DiscriminatorValue("Car")
      public class Car extends Vehicle{        //Vehicle的子类
      private String engine;//发动机
      @Column(nullable=true,length=30)
      public String getEngine() {
      return engine;
      }
      public void setEngine(String engine) {
      this.engine = engine;
            }
      }
       @SuppressWarnings("serial")
       @Entity
       @DiscriminatorValue("Camion")
       public class Camion extends Car{           //Car的子类
       private String container;//集装箱
       @Column(nullable=true,length=30)
       public String getContainer() {
       return container;
       }
       public void setContainer(String container) {
       this.container = container;
              }
       }
分析:
         可
以看出,每个子类没有单独的映射,在数据库中没有对应的表存在。而只有一个记录所有自身属性和子类所有属性的表,在基类为Vehicle
的时候,Discriminator 字段的值将为Vehicle,在子类为Car 的时候,Discriminator
字段的值将为Car,子类为Camion 的时候,Discriminator 字段的值将为Camion。那么,如果业务逻辑要求Car
对象的engine 属性不允许为null,显然无法在Vehicle_Hierarchy 表中为engine 字段定义not null
约束,可见这种映射方式无法保证关系数据模型的数据完整性。
二、每个类分层结构一张表(table per class hierarchy)
      
这种映射方式为每个类创建一个表。在每个类对应的表中只需包含和这个类本身的属性对应的字段,子类对应的表参照父类对应的表,使用每个子类一张表
(table per subclass)策略,需要把@javax.persistence.Inheritance 注释的strategy 属性设置为InheritanceType.JOINED
      @SuppressWarnings("serial")
      @Entity
      @Inheritance(strategy=InheritanceType.JOINED)
      @Table(name="Vehicle")
      public class Vehicle implements Serializable{      //基类
      private Long id;
      private Short speed;//速度
      @Id
      @GeneratedValue
      @Column(columnDefinition="integer")
      public Long getId() {
      return id;
      }
      public void setId(Long id) {
      this.id = id;
      }
      public Short getSpeed() {
      return speed;
      }
      public void setSpeed(Short speed) {
      this.speed = speed;
      }
      }
      @SuppressWarnings("serial")
      @Entity
      @Table(name="Car")
      @PrimaryKeyJoinColumn(name="CarID")      //把主键对应的列名更改为CarID
      public class Car extends Vehicle{                  //Vehicle的子类
      private String engine;//发动机
      @Column(nullable=true,length=30)
      public String getEngine() {
      return engine;
      }
      public void setEngine(String engine) {
      this.engine = engine;
      }
      }
      @SuppressWarnings("serial")
      @Entity
      @Table(name="Camion")
      @PrimaryKeyJoinColumn(name="CamionID")      //把主键对应的列名更改为CamionID
      public class Camion extends Car{                     //Car的子类
      private String container;
      @Column(nullable=true,length=30)
      public String getContainer() {
      return container;
      }
      public void setContainer(String container) {
      this.container = container;
      }
      }
         这种映射方式支持多态关联和多态查询,而且符合关系数据模型的常规设计规则。在这种策略中你可以对子类的属性对应的字段定义not null 约束。该策略的缺点:
         它的查询性能不如上面介绍的映射策略。在这种映射策略下,必须通过表的内连接或左外连接来实现多态查询和多态关联。
选择原则:子类属性非常多,需要对子类某些属性对应的字段进行not null 约束,且对性能要求不是很严格时,优先选择该策略
三、每个具体类一张表(table per concrete class)
      
这种映射方式为每个类创建一个表。在每个类对应的表中包含和这个类所有属性(包括从超类继承的属性)对应的字段,使用每个具体类一张表(table
per concrete class)策略,需要把@javax.persistence.Inheritance 注释的strategy 属性设置为InheritanceType.TABLE_PER_CLASS
         注意:一旦使用这种策略就意味着你不能使用AUTO generator 和IDENTITY generator,即主键值不能采用数据库自动生成.
      @SuppressWarnings("serial")
      @Entity
      @Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
      @Table(name="Vehicle")
     public class Vehicle implements Serializable{             //基类
      private Long id;
      private Short speed;//速度
      @Id
      @Column(columnDefinition="integer")
      public Long getId() {
      return id;
      }
      public void setId(Long id) {
      this.id = id;
      }
      public Short getSpeed() {
      return speed;
      }
      public void setSpeed(Short speed) {
      this.speed = speed;
      }
      }
      @SuppressWarnings("serial")
      @Entity
      @Table(name="Car")
    public class Car extends Vehicle{                 //Vehicle的子类
      private String engine;//发动机
      @Column(nullable=true,length=30)
      public String getEngine() {
      return engine;
      }
      public void setEngine(String engine) {
      this.engine = engine;
      }
      }
      @SuppressWarnings("serial")
      @Entity
      @Table(name="Camion")
      public class Camion extends Car{               //Car的子类
      private String container;//集装箱
      @Column(nullable=true,length=30)
      public String getContainer() {
      return container;
      }
      public void setContainer(String container) {
      this.container = container;
      }
      }
注意:在查询时,例如: from Vehicle v
          查询所有Vehicle时,因为他是最继承树中的根,查询结果会得到所有继承于Vehicle类的记录
(构造的SQL Where部分:where Discriminator in ('Car', 'Camion'))
          delete from Vehicle v
          执行该操作会删除自身对应记录,还会删除所有继承Vehicle的记录,因为他是最继承树中的根,就相当于清除整个表的数据
该策略的优点:
                      在这种策略中你可以对子类的属性对应的字段定义not null 约束。
该策略的缺点:
                    
不符合关系数据模型的常规设计规则,每个表中都存在属于基类的多余的字段。同时,为了支持策略的映射,持久化管理者需要决定使用什么方法,一种方法是在
entity
载入或多态关联时,容器使用多次查询去实现,这种方法需要对数据库做几次来往查询,非常影响执行效率。另一种方法是容器通过使用SQLUNIOU
查询来实现这种策略。
选择原则:
                      除非你的现实情况必须使用这种策略,一般情况下不要选择。