HibernateJPA中的继承映射 实体extends的关系(每个子类独立一个表)

    技术2022-06-25  42

    Hibernate/JPA中的继承映射

    Hibernate中的继承映射

     

    Hibernate的继承映射包含了三种不同的策略:

    每簇类使用一个表; 每个子类一个表; 每个具体内一个表(有限制)。

    假设我们有四个类Animal,Dog,Cat,其代码如下:文件名:Animal.java

    class Animal {    private String identifier;    private String name;    private String category;    // setter and getter}

    文件名:Dog.java

    class Dog extends Animal {    private String     // setter and getter}

    文件名:Cat.java

    class Cat extends Animal {    private String     // setter and getter}

     

    每簇类使用一个表

           使用每簇类使用一个表的策略时,有一个限制就时子类不能有NOT NULL,映射文件为:       文件名:Animal.hbm.xml

            < class name ="Animal" table ="TB_ANIMAL" >            < id name ="identifier" type ="string" column ="IDENTIFIER" >               < generator class ="uuid.hex" />            </ id >            < discriminator column ="ANIMAL_TYPE" type ="string" />            < property name ="name" column ="NAME" type ="string" />                      < subclass name ="Dog" discriminator-value ="DOG" >                         </ subclass >            < subclass name ="Cat" discriminator-value ="CAT" >                         </ subclass >         </ class >

     

    每个子类一个表

           使用每个子类一个表的策略时,可以使用一个映射文件实现,也可以分成多个映射文件来实现。每个子类一个映射文件的情况:       文件名:Animal.hbm.xml

            < class name ="Animal" table ="ANIMAL" >            < id name ="identifier" column ="IDENTIFIER" type ="string" >               < generator class ="uuid.hex" />            </ id >            < property >         </ class >         文件名:Dog.hbm.xml        < joined-subclass name ="Dog" table ="DOG" extends ="Animal" >            < key column ="DOG_ID" />                   </ joined-subclass >         文件名:Cat.hbm.xml        < joined-subclass name ="Cat" table ="CAT" extends ="Cat" >            < key column ="CAT_ID" />                   </ joined-subclass >

           每个子类一个表的策略实际上一种one-to-one的映射。

    每个具体内一个表(有限制)

           使用每个具体内一个表(有限制)策略时,每一个子类的映射文件将要包含所有父类中的属性,映射文件:       文件名:Dog.hbm.xml

            < class name ="Dog" table ="DOG" >            < id name ="identifier" column ="IDENTIFIER" type ="string" >               < generator class ="uuid.hex" />            </ id >            < property name ="name" column ="NAME" type ="string" />                   </ class >         文件名:Cat.hbm.xml        < class name ="Cat" table ="CAT" >            < id name ="identifier" column ="IDENTIFIER" type ="string" >               < generator class ="uuid.hex" />            </ id >            < property name ="name" column ="NAME" type ="string" />                   </ class >

     

    JPA中的实体层次设计

    这部分的内容基本与Hibernate一致.JPA同样支持3种类型的继承形式:

    1.Single Table Strategy ,单表策略,一张表包含基类与子类的所有数据,很多情况下都是采用这样的冗余设计,通过一个discriminator来区分

    2.Table Per Class Strategy ,每个子类对应一张表,每张表都拥有基类的属性

    3.Join Strategy ,仍然是每个子类对应一张表,但此表中不包含基类的属性,仅仅是此子类的扩展属性,共享基类的属性

     

    以一个例子来说明3种情况:

    一.单表策略

    比如Pet作为基类,Cat和Dog继承此类并拥有自己的扩展属性,如:

    package com.denny_blue.ejb3.inheritance;

    import java.io.Serializable;

    import javax.persistence.DiscriminatorColumn;import javax.persistence.DiscriminatorType;import javax.persistence.Entity;import javax.persistence.GeneratedValue;import javax.persistence.GenerationType;import javax.persistence.Id;import javax.persistence.Inheritance;import javax.persistence.InheritanceType;

    @Entity@Inheritance(strategy = InheritanceType.SINGLE_TABLE)@DiscriminatorColumn(name = "animal_type", discriminatorType = DiscriminatorType.STRING)public class Pet implements Serializable {private int id;

    private String name;

    private double weight;

    public Pet() {}

    @Id@GeneratedValue(strategy = GenerationType.AUTO)public int getId() {   return id;}

    public void setId(int id) {   this.id = id;}

    public String getName() {   return name;}

    public void setName(String name) {   this.name = name;}

    public double getWeight() {   return weight;}

    public void setWeight(double weight) {   this.weight = weight;}

    }

    Pet类值的注意的就是通过@Inheritance(strategy = InheritanceType.SINGLE_TABLE)确定采用单表策略,通过@DiscriminatorColumn确定了标志值的字段和类型,我想熟悉hibernate的朋友对这些都应该很熟悉.然后是两个子类:

    //Cat.java

    package com.denny_blue.ejb3.inheritance;

    import javax.persistence.DiscriminatorColumn;import javax.persistence.DiscriminatorType;import javax.persistence.DiscriminatorValue;import javax.persistence.Entity;import javax.persistence.Inheritance;import javax.persistence.InheritanceType;

    @Entity@Inheritance(strategy = InheritanceType.SINGLE_TABLE)@DiscriminatorColumn(discriminatorType = DiscriminatorType.STRING)@DiscriminatorValue("cat")public class Cat extends Pet {private String HairBall;

    public String getHairBall() {   return HairBall;}

    public void setHairBall(String hairBall) {   HairBall = hairBall;}

    }

    //Dog.java

    package com.denny_blue.ejb3.inheritance;

    import javax.persistence.DiscriminatorColumn;import javax.persistence.DiscriminatorType;import javax.persistence.DiscriminatorValue;import javax.persistence.Entity;import javax.persistence.Inheritance;import javax.persistence.InheritanceType;

    @Entity@Inheritance(strategy=InheritanceType.SINGLE_TABLE)@DiscriminatorColumn(discriminatorType=DiscriminatorType.STRING)@DiscriminatorValue("dog")public class Dog extends Pet {private String trick;

    public String getTrick() {   return trick;}

    public void setTrick(String trick) {   this.trick = trick;}

    }

    两个子类最值的关注的就是@DiscriminatorValue注释,比如Cat的此值为cat,意味着当Cat类型的Entity存入数据库时,JPA将自动把cat的值赋给animal_type字段,Dog的值则为dog,由此就可以在同一张表中区分开两个不同的子类.

     

    二.Table per Class

    采用Table Per Class策略的话,每个子类都将单独建表,并且都独立拥有基类中的所有属性,互相之间不共享,在我们的例子中所要进行的修改很小,像这样:

    //基类

    @Entity@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)public class Pet implements Serializable {private int id;

    private String name;

    private double weight;

    ........

    //子类:不需要任何设置

    @Entitypublic class Dog extends Pet {private String trick;

    .......

    .......

    }

    例:

    @Entity@Table(name = "TEST_A")@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)public class TestA implements java.io.Serializable {

    // Fields

    /*** */private static final long serialVersionUID = 5931010626625178698L;private Long id;private String name;private String code;

    // Constructorspublic TestA() {

    }

    /** minimal constructor */public TestA(Long id) {   this.id = id;}

    /** full constructor */public TestA(Long id, String name, String code) {   this.id = id;   this.name = name;   this.code = code;}

    // Property accessors@Id@Column(name = "ID")@GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ")@SequenceGenerator(name="SEQ", sequenceName = "SEQ_TEMP_VOICE_FILE")public Long getId() {   return this.id;}

    public void setId(Long id) {   this.id = id;}

    @Column(name = "NAME", unique = false, nullable = true, insertable = true, updatable = true, length = 200)public String getName() {   return this.name;}

    public void setName(String name) {   this.name = name;}

    @Column(name = "CODE", unique = false, nullable = true, insertable = true, updatable = true, length = 200)public String getCode() {   return this.code;}

    public void setCode(String code) {   this.code = code;}

    }

    @Entity@Table(name = "TEST_B")public class TestB extends TestA {

    // Fields

    /*** */private static final long serialVersionUID = 4942564072409132522L;

    /** minimal constructor */public TestB() {

    }public TestB(Long id) {   this.setId(id);}

    @Column(name = "FLAG", unique = false, nullable = true, insertable = true, updatable = true, precision = 1, scale = 0)public Long getFlag() {   return this.flag;}

    public void setFlag(Long flag) {   this.flag = flag;}

    }

     

    三.Join策略

    每个子类同样独立建表,基类也独立建表,只不过所有的子类的表中只有扩展属性,他们共享基类的表,在我们的例子中修改下即可:

    //基类

    @Entity@Inheritance(strategy = InheritanceType.JOINED)public class Pet implements Serializable {private int id;

    private String name;

    private double weight;

    ........

    //子类

    @Entity

    @Inheritance(strategy = InheritanceType.JOINED)public class Dog extends Pet {private String trick;

     


    最新回复(0)