導(dǎo)讀:
- 什么是繼承映射篙耗?
- 繼承映射的分類
- 所有類形成一張表
- 每個類形成一張表
- 只有子類生成表铃岔,父類不生成表
Paste_Image.png
什么是繼承映射
實體類之間互相有繼承關(guān)系,或者說多個實體類有公共部分叮喳,可以抽象出一個父類钝诚。這是對象之間的關(guān)系颖御,可是數(shù)據(jù)表存儲不一定是一個類對應(yīng)一張表,因此我們需要分類討論一下凝颇。
繼承映射的分類
上面已經(jīng)說過了潘拱,一共分成三種情況,其實對象之間的關(guān)系沒有變拧略,這三種情況都是表達了數(shù)據(jù)表的對應(yīng)關(guān)系芦岂。
在講具體每種情況前,先把各實體類代碼貼出來:
Animal.java
package entity;
public class Animal {
private int id;
private String name;
private boolean sex;
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 boolean isSex() {
return sex;
}
public void setSex(boolean sex) {
this.sex = sex;
}
}
Pig.java
package entity;
public class Pig extends Animal{
private int weight;
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
}
Dog.java
package entity;
public class Dog extends Animal{
private int run;
public int getRun() {
return run;
}
public void setRun(int run) {
this.run = run;
}
}
1.所有類形成一張表
Animal.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="entity.Animal" table="_animal">
<id name="id">
<generator class="native"/>
</id>
<!-- 下面就開始定義就是將pig和dog繼承進來垫蛆,都生成一張表 -->
<!-- 下面的這個類型string是hibernate的禽最,不是java自己的String類型 -->
<!-- discriminator這個標(biāo)簽必須寫在所有屬性的第一個腺怯,要不然會報錯! -->
<discriminator column="type" type="string" />
<property name="name" />
<property name="sex" />
<subclass name="entity.Pig" discriminator-value="P">
<property name="weight"></property>
</subclass>
<subclass name="entity.Dog" discriminator-value="D">
<property name="run"></property>
</subclass>
</class>
</hibernate-mapping>
單元測試:
package entity;
import org.hibernate.classic.Session;
import junit.framework.TestCase;
import util.hibernateUtil;
/**
* 測試目的:
* 這是繼承映射的第一種策略川无,多個類共同對應(yīng)一張表呛占。
* 1. 用不同的子類去查詢數(shù)據(jù)
* 2. 用父類多態(tài)的角度去查詢
* 3. 根據(jù)不同的類查詢出來結(jié)果,因為涉及到延遲加載懦趋,看是否能判斷真實類類型
*
* 結(jié)果:
* 只要是查詢的時候不延時晾虑,那就能判斷實際的對象類型
* @author arkulo
*
*/
public class TestDemo extends TestCase {
// 初始化數(shù)據(jù)
public void test1()
{
Session session = null;
try {
session = hibernateUtil.getSession();
session.beginTransaction();
Dog dd = new Dog();
dd.setName("叮當(dāng)");
dd.setSex(false);
dd.setRun(100);
session.save(dd);
Pig zz = new Pig();
zz.setName("八戒");
zz.setSex(false);
zz.setWeight(60);
session.save(zz);
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally{
hibernateUtil.closeSession(session);
}
}
// 用父類多態(tài)角度去查詢
public void test2()
{
test1();
System.out.println("----------------------------");
Session session = null;
try {
session = hibernateUtil.getSession();
session.beginTransaction();
// load是延遲加載,所以用的是代理仅叫,因此不能判斷對象的類型是Dog
// 如果必須判斷真實對象類型帜篇,那就該用get函數(shù),或者把class的lazy屬性設(shè)置成為false
// Animal an = (Animal)session.load(Animal.class, 1);
// if(an instanceof Dog)
// {
// System.out.println("我是小狗诫咱,我叫:"+an.getName());
// }else
// {
// System.out.println("我是小豬笙隙,我叫"+an.getName());
// }
Dog dd = (Dog)session.get(Dog.class, 1);
System.out.println(dd.getName());
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally{
hibernateUtil.closeSession(session);
}
}
}
2.每個類形成一張表
Animal.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="entity">
<class name="entity.Animal" table="_animal">
<id name="id">
<generator class="native"/>
</id>
<property name="name" />
<property name="sex" />
<!-- 下面就是各個實體類單獨程表的映射配置 -->
<!-- pid是關(guān)聯(lián)animal表的主鍵,did同理 -->
<joined-subclass name="Pig" table="_pig">
<key column="pid"></key>
<property name="weight"></property>
</joined-subclass>
<joined-subclass name="Dog" table="_dog">
<key column="did"></key>
<property name="run"></property>
</joined-subclass>
</class>
</hibernate-mapping>
單元測試:
package entity;
import org.hibernate.classic.Session;
import junit.framework.TestCase;
import util.hibernateUtil;
/**
* 這個項目是多個關(guān)聯(lián)實體類坎缭,每個實體類映射成為一張表竟痰,但是只用一個hbm映射文件
* 插入數(shù)據(jù)的時候,相當(dāng)于主附表
*
* @author arkulo
*
*/
public class TestDemo extends TestCase {
// 初始化數(shù)據(jù)
public void test1()
{
Session session = null;
try {
session = hibernateUtil.getSession();
session.beginTransaction();
// 產(chǎn)生兩天sql語句掏呼,一條插入Animal表凯亮,一條插入Dog表,did字段關(guān)聯(lián)animal表的主鍵
Dog dd = new Dog();
dd.setName("叮當(dāng)");
dd.setSex(false);
dd.setRun(100);
session.save(dd);
// 和上面同理哄尔,產(chǎn)生兩條SQL語句
Pig zz = new Pig();
zz.setName("八戒");
zz.setSex(false);
zz.setWeight(60);
session.save(zz);
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally{
hibernateUtil.closeSession(session);
}
}
// 用父類多態(tài)角度去查詢
public void test2()
{
test1();
System.out.println("----------------------------");
Session session = null;
try {
session = hibernateUtil.getSession();
session.beginTransaction();
// load是延遲加載,所以用的是代理柠并,因此不能判斷對象的類型是Dog
// 如果必須判斷真實對象類型岭接,那就該用get函數(shù),或者把class的lazy屬性設(shè)置成為false
// sql語句是left out join臼予,一條SQL語句聯(lián)合查詢兩張表
// Animal an = (Animal)session.load(Animal.class, 1);
// if(an instanceof Dog)
// {
// System.out.println("我是小狗鸣戴,我叫:"+an.getName());
// }else
// {
// System.out.println("我是小豬,我叫"+an.getName());
// }
// 采用inner join的方式粘拾,發(fā)出一條sql語句窄锅,關(guān)聯(lián)查詢animal和dog表
// Dog dd = (Dog)session.get(Dog.class, 1);
// System.out.println(dd.getName());
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally{
hibernateUtil.closeSession(session);
}
}
}
3.只有子類生成表,父類不生成表
Animal.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="entity">
<!-- abstract設(shè)置為true缰雇,animal實體類就不會建表入偷,但不會影響到存儲和加載 -->
<class name="entity.Animal" abstract="true">
<id name="id">
<!-- 這里不會生成表了,所以id就不能采用數(shù)據(jù)庫生成策略 -->
<generator class="assigned"/>
</id>
<property name="name" />
<property name="sex" />
<!-- 下面開始配置子類生成獨立的表 -->
<union-subclass name="Pig" table="_pig">
<property name="weight"></property>
</union-subclass>
<union-subclass name="Dog" table="_dog">
<property name="run"></property>
</union-subclass>
</class>
</hibernate-mapping>
單元測試:
package entity;
import org.hibernate.classic.Session;
import junit.framework.TestCase;
import util.hibernateUtil;
/**
* 三個類械哟,每個具體類映射成一張表疏之,父類不映射成表
*
* @author arkulo
*
*/
public class TestDemo extends TestCase {
// 初始化數(shù)據(jù)
public void test1()
{
Session session = null;
try {
session = hibernateUtil.getSession();
session.beginTransaction();
// 這里要注意,id是由animal提供的暇咆,但是animal現(xiàn)在不會在去生成表了锋爪,因此
// 這里的主鍵丙曙,我們只能自己指定,不能依靠數(shù)據(jù)庫生成其骄,當(dāng)然也可以使用uuid亏镰,那就需要設(shè)置id為String類型
Dog dd = new Dog();
dd.setId(1);
dd.setName("叮當(dāng)");
dd.setSex(false);
dd.setRun(100);
session.save(dd);
// 和上面同理
Pig zz = new Pig();
zz.setId(2);
zz.setName("八戒");
zz.setSex(false);
zz.setWeight(60);
session.save(zz);
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally{
hibernateUtil.closeSession(session);
}
}
// 用父類多態(tài)角度去查詢
public void test2()
{
// 這里如果用上面的函數(shù)來初始化數(shù)據(jù),記得重新指定id拯爽,因為是手動設(shè)定的
test1();
System.out.println("----------------------------");
Session session = null;
try {
session = hibernateUtil.getSession();
session.beginTransaction();
// load是延遲加載索抓,所以用的是代理,因此不能判斷對象的類型是Dog
// 如果必須判斷真實對象類型某抓,那就該用get函數(shù)纸兔,或者把class的lazy屬性設(shè)置成為false
// sql語句是left out join,一條SQL語句聯(lián)合查詢兩張表
Animal an = (Animal)session.get(Animal.class, 1);
if(an instanceof Dog)
{
System.out.println("我是小狗否副,我叫:"+an.getName());
}else
{
System.out.println("我是小豬汉矿,我叫"+an.getName());
}
// 采用inner join的方式,發(fā)出一條sql語句备禀,關(guān)聯(lián)查詢animal和dog表
// Dog dd = (Dog)session.get(Dog.class, 1);
// System.out.println(dd.getName());
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally{
hibernateUtil.closeSession(session);
}
}
}