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

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

http://blog.csdn.net/skytalemcc/archive/2010/01/15/5196286.aspx

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

每簇类使用一个表;

每个子类一个表;

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

假设我们有四个类Animal,Dog,Cat,其代码如下:

文件名:Animal.java

class Animal {

privateStringidentifier;

privateStringname;

privateStringcategory;

//setterandgetter

}

文件名:Dog.java

class Dog extends Animal {

privateString

//setterandgetter

}

文件名:Cat.java

class Cat extends Animal {

privateString

//setterandgetter

}

每簇类使用一个表

使用每簇类使用一个表的策略时,有一个限制就时子类不能有NOTNULL,映射文件为:

       文件名:Animal.hbm.xml

       <class name="Animal" table="TB_ANIMAL">

<idname="identifier"type="string"column="IDENTIFIER">

<generatorclass="uuid.hex"/>

</id>

<discriminatorcolumn="ANIMAL_TYPE"type="string"/>

<propertyname="name"column="NAME"type="string"/>

<subclassname="Dog"discriminator-value="DOG">

</subclass>

<subclassname="Cat"discriminator-value="CAT">

</subclass>

</class>

每个子类一个表

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

       文件名:Animal.hbm.xml

       <class name="Animal" table="ANIMAL">

<idname="identifier"column="IDENTIFIER"type="string">

<generatorclass="uuid.hex"/>

</id>

<property>

</class>

文件名:Dog.hbm.xml

<joined-subclassname="Dog"table="DOG"extends="Animal">

<keycolumn="DOG_ID"/>

</joined-subclass>

文件名:Cat.hbm.xml

<joined-subclassname="Cat"table="CAT"extends="Cat">

<keycolumn="CAT_ID"/>

       </joined-subclass>

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

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

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

       文件名:Dog.hbm.xml

       <class name="Dog" table="DOG">

<idname="identifier"column="IDENTIFIER"type="string">

<generatorclass="uuid.hex"/>

</id>

<propertyname="name"column="NAME"type="string"/>

</class>

文件名:Cat.hbm.xml

<classname="Cat"table="CAT">

<idname="identifier"column="IDENTIFIER"type="string">

<generatorclass="uuid.hex"/>

</id>

<propertyname="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;

importjavax.persistence.DiscriminatorType;

importjavax.persistence.Entity;

importjavax.persistence.GeneratedValue;

importjavax.persistence.GenerationType;

importjavax.persistence.Id;

importjavax.persistence.Inheritance;

import javax.persistence.InheritanceType;

@Entity

@Inheritance(strategy=InheritanceType.SINGLE_TABLE)

@DiscriminatorColumn(name="animal_type",discriminatorType=DiscriminatorType.STRING)

publicclassPetimplementsSerializable{

private int id;

private String name;

private double weight;

public Pet() {}

@Id

@GeneratedValue(strategy=GenerationType.AUTO)

publicintgetId(){

returnid;

}

public void setId(int id) {

this.id=id;

}

public String getName() {

returnname;

}

public void setName(String name) {

this.name=name;

}

public double getWeight() {

returnweight;

}

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;

importjavax.persistence.DiscriminatorType;

importjavax.persistence.DiscriminatorValue;

importjavax.persistence.Entity;

importjavax.persistence.Inheritance;

import javax.persistence.InheritanceType;

@Entity

@Inheritance(strategy=InheritanceType.SINGLE_TABLE)

@DiscriminatorColumn(discriminatorType=DiscriminatorType.STRING)

@DiscriminatorValue("cat")

publicclassCatextendsPet{

private String HairBall;

public String getHairBall() {

returnHairBall;

}

public void setHairBall(String hairBall) {

HairBall=hairBall;

}

}

//Dog.java

package com.denny_blue.ejb3.inheritance;

import javax.persistence.DiscriminatorColumn;

importjavax.persistence.DiscriminatorType;

importjavax.persistence.DiscriminatorValue;

importjavax.persistence.Entity;

importjavax.persistence.Inheritance;

import javax.persistence.InheritanceType;

@Entity

@Inheritance(strategy=InheritanceType.SINGLE_TABLE)

@DiscriminatorColumn(discriminatorType=DiscriminatorType.STRING)

@DiscriminatorValue("dog")

publicclassDogextendsPet{

private String trick;

public String getTrick() {

returntrick;

}

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)

publicclassPetimplementsSerializable{

private int id;

private String name;

private double weight;

........

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

@Entity

publicclassDogextendsPet{

private String trick;

.......

.......

}

例:

@Entity

@Table(name="TEST_A")

@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)

public class TestA implements java.io.Serializable {

// Fields

/**

*

*/

privatestaticfinallongserialVersionUID=5931010626625178698L;

privateLongid;

privateStringname;

private String code;

// Constructorspublic TestA() {

}

/** minimal constructor */

publicTestA(Longid){

this.id=id;

}

/** full constructor */

publicTestA(Longid,Stringname,Stringcode){

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")

publicLonggetId(){

returnthis.id;

}

public void setId(Long id) {

this.id=id;

}

@Column(name = "NAME", unique = false, nullable = true, insertable = true, updatable = true, length = 200)

publicStringgetName(){

returnthis.name;

}

public void setName(String name) {

this.name=name;

}

@Column(name = "CODE", unique = false, nullable = true, insertable = true, updatable = true, length = 200)

publicStringgetCode(){

returnthis.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;

/**minimalconstructor*/

public TestB() {

}

publicTestB(Longid){

this.setId(id);

}

@Column(name = "FLAG", unique = false, nullable = true, insertable = true, updatable = true, precision = 1, scale = 0)

publicLonggetFlag(){

returnthis.flag;

}

public void setFlag(Long flag) {

this.flag=flag;

}

}

三.Join策略

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

//基类

@Entity

@Inheritance(strategy=InheritanceType.JOINED)

publicclassPetimplementsSerializable{

private int id;

private String name;

private double weight;

........

//子类

@Entity

@Inheritance(strategy = InheritanceType.JOINED)

publicclassDogextendsPet{

private String trick;

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/skytalemcc/archive/2010/01/15/5196286.aspx

相关推荐