Hibernate/JPA中的继承映射 实体extends的关系(每个子类独立一个表)
Hibernate/JPA中的继承映射 实体extends的关系(每个子类独立一个表)
http://blog.csdn.net/skytalemcc/archive/2010/01/15/5196286.aspx
Hibernate的继承映射包含了三种不同的策略:
每簇类使用一个表;
每个子类一个表;
每个具体内一个表(有限制)。
假设我们有四个类Animal,Dog,Cat,其代码如下:
文件名:Animal.javaclass 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