Hibernate高级映射 --- 继承映射

本文详细介绍了Hibernate中的继承映射,包括四种常用的映射方式及其特点,通过实例代码展示了如何实现不同类型的继承映射,并探讨了各自的优缺点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Hibernate高级映射 --- 继承映射

一 概念

继承是面向对象编程中一个很重要的特征,在做面向对象的分析与设计时,经常会设计出具体继承关联的持久化类。

二 四种常用的映射方式

1.设计整个的继承体现就用一张表 employee

属性为id,name,depart_id,type,skill,sell

0 null null

1 coding null

2 null 100

说明:type是鉴别器,type中0表示普通员工,1表示技术员工,2表示销售员工

(1)创建父类 Employee

package com.hbsi.domain;

public class Employee {

private int id;

private String name;

public Employee() {

super();

// TODO Auto-generated constructor stub

}

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 Department getDepart() {

return depart;

}

public void setDepart(Department depart) {

this.depart = depart;

}

}

(2)创建子类 Skiller

package com.hbsi.domain;

public class Skiller extends Employee {

private String skill;

public String getSkill() {

return skill;

}

public void setSkill(String skill) {

this.skill = skill;

}

}

(3)创建子类 Sales

package com.hbsi.domain;

public class Sales extends Employee {

private Integer sell;

public Integer getSell() {

return sell;

}

public void setSell(Integer sell) {

this.sell = sell;

}

}

(4)映射一张表:

<?xml version="1.0"?>

<!DOCTYPE hibernate-mapping PUBLIC

"-//Hibernate/Hibernate Mapping DTD 3.0//EN"

"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="com.hbsi.domain">

<!-- discriminator-value="0"指定鉴别器在什么的时候属于哪个类型 -->

<class name="Employee" table="employee" discriminator-value="0">

<id name="id" column="id">

<generator class="native" />

</id>

<!-- 定义鉴别器,缺省的类型是字符串类型 鉴别器的位置应该在前面 -->

<discriminator column="type" type="int"/>

<property name="name" column="name" />

<!-- 用来描述子类,是继承映射 -->

<subclass name="Skiller" discriminator-value="1">

<property name="skill"></property>

</subclass>

<subclass name="Sales" discriminator-value="2">

<property name="sell"></property>

</subclass>

</class>

</hibernate-mapping>

(5)持久化类

package com.hbsi.test;

import org.hibernate.Session;

import org.hibernate.Transaction;

import com.hbsi.domain.Department;

import com.hbsi.domain.Employee;

import com.hbsi.domain.Sales;

import com.hbsi.domain.Skiller;

import com.hbsi.hibernate.utils.HibernateUtil;

public class TestExtends {

public static void main(String[] args) {

//add();

query(19);

}

static void add() {

Session session = null;

Transaction transaction = null;

try {

session = HibernateUtil.getSession();

transaction = session.beginTransaction();

// 普通员工

Employee emp1 = new Employee();

emp1.setName("aaa");

emp1.setDepart(depart);

// 技术员工

Skiller emp2 = new Skiller();

emp2.setName("bbb");

emp2.setDepart(depart);

emp2.setSkill("coding");

// 销售员工

Sales emp3 = new Sales();

emp3.setName("ccc");

emp3.setDepart(depart);

emp3.setSell(1000);

session.save(emp1);

session.save(emp2);

session.save(emp3);

transaction.commit();

} finally {

if (session != null) {

session.close();

}

}

}

//查询

static void query(int id) {

Session session = null;

try {

session = HibernateUtil.getSession();

//多态查询

Employee employee = (Employee) session.get(Employee.class, id);

System.out.println(employee.getName()+":"+employee.getClass());

//查询出子类中的属性

if(employee instanceof Skiller){

((Skiller) employee).getSkill();

}else if(employee instanceof Sales){

((Sales) employee).getSell();

}

} finally {

if (session != null) {

session.close();

}

}

}

}

思考:

优点:在性能和简单性方面都很好,在多态和非多态的查询上也表现的很好,是继承映射中使用比较广泛的方案。

缺点:如果Skill中有多个属性来描述,那么在员工的表中有5个字段为空的,如果Sales中也有多个属性,也会出现大量的null值,这种映射方案的关系模型表设计业违背了第三范式。

2.每个子类一张表(joined-subclass),存放的是子类所特有的属性

Employee Skiller Salles

Id name depar_id employee_id,skill employee_id,sell

映射文件为:

<?xml version="1.0"?>

<!DOCTYPE hibernate-mapping PUBLIC

"-//Hibernate/Hibernate Mapping DTD 3.0//EN"

"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="com.hbsi.domain">

<!-- 继承映射第二种 单独映射为一张表 -->

<class name="Employee" table="employee1">

<id name="id">

<generator class="native"></generator>

</id>

<property name="name" column="name" />

<many-to-one name="depart" column="depart_id"/>

<!-- 单独映射成一张表,来描述特有的属性 -->

<joined-subclass name="Skiller" table="skiller">

<key column="employee_id"></key>

<property name="skill"></property>

</joined-subclass>

<joined-subclass name="Sales" table="sales">

<key column="employee_id"></key>

<property name="sell"></property>

</joined-subclass>

</class>

</hibernate-mapping>

思考:

这种效率是不高的,因为在多态查询的时候要同时连接三张表,如果再增加一个子类,那么在关系模型中增加了一个表,多态的查询要四张表,如果是更多呢?

但是这种方式采用的设计模式是合理的,可效率不高

3.混合使用”一个类继承体系一张表”和”每个子类一张表”,

Employee sales

Id,name,dpart_id,type skill employee_id,sell

<?xml version="1.0"?>

<!DOCTYPE hibernate-mapping PUBLIC

"-//Hibernate/Hibernate Mapping DTD 3.0//EN"

"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="com.hbsi.domain">

<!-- 第三种 :前两种的混合-->

<class name="Employee" table="employee2" discriminator-value="0">

<id name="id">

<generator class="native"></generator>

</id>

<!-- 鉴别器 -->

<discriminator column="type" type="int"/>

<property name="name" column="name" />

<many-to-one name="depart" column="depart_id"/>

<subclass name="Skiller" discriminator-value="1">

<property name="skill"/>

</subclass>

<subclass name="Sales" discriminator-value="2">

<join table="sales1">

<key column="employee_id"/>

<property name="sell"/>

</join>

</subclass>

</class>

</hibernate-mapping>

4.每个具体类是一张完整的表(union-subclass),保存子类完整的信息

<?xml version="1.0"?>

<!DOCTYPE hibernate-mapping PUBLIC

"-//Hibernate/Hibernate Mapping DTD 3.0//EN"

"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="com.hbsi.domain">

<!-- 第四种 每一个表都是完整的表 -->

<class name="Employee" table="employee4">

<id name="id">

<!-- 表示高地位的主键生成器 形成唯一的主键 -->

<generator class="hilo"/>

</id>

<property name="name" column="name" />

<many-to-one name="depart" column="depart_id"/>

<!-- 连接 -->

<union-subclass name="Skiller" table="skiller4">

<property name="skill"></property>

</union-subclass>

<union-subclass name="Sales" table="sale4">

<property name="sell"></property>

</union-subclass>

</class>

</hibernate-mapping>

总体的建议:表的数量不要超过类的数量

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值