Hibernate繼承映射

Hibernate繼承映射

  在面向對象的程序領域中,類與類之間是有繼承關係的,例如Java世界中只須要extends關鍵字就能夠肯定這兩個類的父子關係,可是在關係數據庫的世界中,表與表之間沒有任何關鍵字能夠明確指明這兩張表的父子關係,表與表是沒有繼承關係這樣的說法的。爲了將程序領域中的繼承關係反映到數據中,Hibernate爲咱們提供了3中方案:html

第一種方案:一個子類對應一張表。數據庫

第二種方案:使用一張表表示全部繼承體系下的類的屬性的並集。app

第三種方案:每一個子類使用一張表只存儲它特有的屬性,而後與父類所對應的表以一對一主鍵關聯的方式關聯起來。post

 

如今假設有People、Student、Teacher三個類,父類爲People,Student與Teacher爲People的父類,代碼以下:ui

People類:this

複製代碼
public class People
{
/*父類所擁有的屬性*/
private String id;
private String name;
private String sex;
private String age;
private Timestamp birthday;

/*get和set方法*/
}
複製代碼

Student類:url

複製代碼
public class Student extends People
{
/*學生獨有的屬性*/
private String cardId;//學號

public String getCardId()
{
return cardId;
}

public void setCardId(String cardId)
{
this.cardId = cardId;
}
}
複製代碼

Teacher類:spa

複製代碼
public class Teacher extends People
{
/*Teacher所獨有的屬性*/
private int salary;//工資

public int getSalary()
{
return salary;
}

public void setSalary(int salary)
{
this.salary = salary;
}
}
複製代碼


第一種方案:一個子類對應一張表 
.net

該方案是使繼承體系中每個子類都對應數據庫中的一張表。示意圖以下:hibernate

 

  每個子類對應的數據庫表都包含了父類的信息,而且包含了本身獨有的屬性。每一個子類對應一張表,並且這個表的信息是完備的,即包含了全部從父類繼承下來的屬性映射的字段。這種策略是使用<union-subclass>標籤來定義子類的。

配置People.hbm.xml文件:

複製代碼
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
<class name="com.suxiaolei.hibernate.pojos.People" abstract="true">
<id name="id" type="string">
<column name="id"></column>
<generator class="uuid"></generator>
</id>

<property name="name" column="name" type="string"></property>
<property name="sex" column="sex" type="string"></property>
<property name="age" column="age" type="string"></property>
<property name="birthday" column="birthday" type="timestamp"></property>

<!--
<union-subclass name="com.suxiaolei.hibernate.pojos.Student" table="student">
<property name="cardId" column="cardId" type="string"></property>
</union-subclass>
<union-subclass name="com.suxiaolei.hibernate.pojos.Teacher" table="teacher">
<property name="salary" column="salary" type="integer"></property>
</union-subclass>

-->

</class>
<union-subclass name="com.suxiaolei.hibernate.pojos.Student"
table
="student" extends="com.suxiaolei.hibernate.pojos.People">
<property name="cardId" column="cardId" type="string"></property>
</union-subclass>

<union-subclass name="com.suxiaolei.hibernate.pojos.Teacher"
table
="teacher" extends="com.suxiaolei.hibernate.pojos.People">
<property name="salary" column="salary" type="integer"></property>
</union-subclass>
</hibernate-mapping>
複製代碼

  以上配置是一個子類一張表方案的配置,<union-subclass>標籤是用於指示出該hbm文件所表示的類的子類,如People類有兩個子類,就須要兩個<union-subclass>標籤以此類推。<union-subclass>標籤的"name"屬性用於指定子類的全限定名稱,"table"屬性用於指定該子類對應的表的名稱,"extends"屬性用於指定該子類的父類,注意該屬性與<union-subclass>標籤的位置有關,若 <union-subclass>標籤做爲<class>標籤的子標籤,則"extends"屬性能夠不設置,不然須要明確設置"extends"屬性。<class>標籤中的"abstract"屬性若是值爲true則,不會生成表結構。若是值爲false則會生成表結構,可是不會插入數據。

根據People.hbm.xml生成表結構:

複製代碼
   drop table if exists student
drop table if exists teacher

create table student (
id varchar(255) not null,
name varchar(255),
sex varchar(255),
age varchar(255),
birthday datetime,
cardId varchar(255),
primary key (id)
)

create table teacher (
id varchar(255) not null,
name varchar(255),
sex varchar(255),
age varchar(255),
birthday datetime,
salary integer,
primary key (id)
)
複製代碼

能夠看到一個子類對應一張表。


第二種方案:使用一張表表示全部繼承體系下的類的屬性的並集

  這種策略是使用<subclass>標籤來實現的。由於類繼承體系下會有許多個子類,要把多個類的信息存放在一張表中,必須有某種機制來區分哪些記錄是屬於哪一個類的。Hibernate中的這種機制就是,在表中添加一個字段,用這個字段的值來進行區分。在表中添加這個標示列使用<discriminator>標籤來實現。

該策略的示意圖:

 

將繼承體系中的全部類信息表示在同一張表中後,只要是這個類沒有的屬性會被自動賦上null。

配置People.hbm.xml:

複製代碼
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
<class name="com.suxiaolei.hibernate.pojos.People" table="people">
<id name="id" type="string">
<column name="id"></column>
<generator class="uuid"></generator>
</id>

<discriminator column="peopleType" type="string"></discriminator>

<property name="name" column="name" type="string"></property>
<property name="sex" column="sex" type="string"></property>
<property name="age" column="age" type="string"></property>
<property name="birthday" column="birthday" type="timestamp"></property>

<subclass name="com.suxiaolei.hibernate.pojos.Student" discriminator-value="student">
<property name="cardId" column="cardId" type="string"></property>
</subclass>

<subclass name="com.suxiaolei.hibernate.pojos.Teacher" discriminator-value="teacher">
<property name="salary" column="salary" type="string"></property>
</subclass>
</class>
</hibernate-mapping>
複製代碼

<discriminator>標籤用於在表中建立一個標識列,其"column"屬性指定標識列的列名,"type"指定了標識列的類型。<subclass>標籤用於指定該HBM文件表明類的子類,有多少子類就有多少個該標籤,其"name"屬性指定子類的名稱,"discriminator-value"屬性指定該子類的數據的標識列的值是什麼,其"extends"屬性與<union-subclass>的"extends"屬性用法一致。

根據People.hbm.xml生成表結構:

複製代碼
    drop table if exists people

create table people (
id varchar(255) not null,
peopleType varchar(255) not null,
name varchar(255),
sex varchar(255),
age varchar(255),
birthday datetime,
cardId varchar(255),
salary varchar(255),
primary key (id)
)
複製代碼

能夠看到一張表將繼承體系下的全部信息都包含了,其中"peopleType"爲標識列。

 

第三種方案:每一個子類使用一張表只存儲它特有的屬性,而後與父類所對應的表以一對一主鍵關聯的方式關聯起來。

  這種策略是使用<joined-subclass>標籤來定義子類的。父類、子類都對應一張數據庫表。在父類對應的數據庫表中,它存儲了全部記錄的公共信息,實際上該父類對應的表會包含全部的記錄,包括父類和子類的記錄;在子類對應的數據庫表中,這個表只定義了子類中所特有的屬性映射的字段。子類對應的數據表與父類對應的數據表,經過一對一主鍵關聯的方式關聯起來。

這種策略的示意圖:

 

  people表中存儲了子類的全部記錄,但只記錄了他們共有的信息,而他們獨有的信息存儲在他們對應的表中,一條記錄要得到其獨有的信息,要經過people記錄的主鍵到其對應的子表中查找主鍵值同樣的記錄而後取出它獨有的信息。

配置People.hbm.xml:

複製代碼
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
<class name="com.suxiaolei.hibernate.pojos.People" table="people">
<id name="id" type="string">
<column name="id"></column>
<generator class="uuid"></generator>
</id>

<property name="name" column="name" type="string"></property>
<property name="sex" column="sex" type="string"></property>
<property name="age" column="age" type="string"></property>
<property name="birthday" column="birthday" type="timestamp"></property>

<joined-subclass name="com.suxiaolei.hibernate.pojos.Student" table="student">
<key column="id"></key>
<property name="cardId" column="cardId" type="string"></property>
</joined-subclass>

<joined-subclass name="com.suxiaolei.hibernate.pojos.Teacher" table="teacher">
<key column="id"></key>
<property name="salary" column="salary" type="integer"></property>
</joined-subclass>
</class>
</hibernate-mapping>
複製代碼

<joined-subclass>標籤須要包含一個key標籤,這個標籤指定了子類和父類之間是經過哪一個字段來關聯的。

根據People.hbm.xml生成表結構:

複製代碼
    drop table if exists people
drop table if exists student
drop table if exists teacher

create table people (
id varchar(255) not null,
name varchar(255),
sex varchar(255),
age varchar(255),
birthday datetime,
primary key (id)
)

create table student (
id varchar(255) not null,
cardId varchar(255),
primary key (id)
)

create table teacher (
id varchar(255) not null,
salary integer,
primary key (id)
)

alter table student
add index FK8FFE823BF9D436B1 (id),
add constraint FK8FFE823BF9D436B1
foreign key (id)
references people (id)

alter table teacher
add index FKAA31CBE2F9D436B1 (id),
add constraint FKAA31CBE2F9D436B1
foreign key (id)
references people (id)
複製代碼

能夠看到,父類對應的表保存公有信息,子類對應的表保存獨有信息,子類和父類對應的表使用一對一主鍵關聯的方式關聯起來                                                                                                                                                  轉自   Hibernate繼承映射 

相關文章
相關標籤/搜索