三、Hibernate组件映射与继承映射

本文探讨了在软件开发中组件映射与继承映射的概念及其应用。详细讲解了类组合关系下的组件映射实现方法,包括单表映射策略,并介绍了继承关系下三种不同的映射配置方式,对比其优缺点。

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

**

组件映射与继承映射

**
类的关系
组合关系
一个类中包含了另外一个类。这2个类中就是组合关系。
需求: 汽车与车轮
继承关系
一个类继承另外一个类。这2个类中就是继承关系。
需求:动物

猴子

1、组件映射
类组合关系的映射,也叫做组件映射!
注意:组件类和被包含的组件类,共同映射到一张表!(所以只有一个映射文件 .hbm.xml,,,而又因为是一张表,所以不用级联)

package cn.itcast.d_component;

public class Car {

private int id;
private String name;
// 车轮
private Wheel wheel;
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 Wheel getWheel() {
    return wheel;
}
public void setWheel(Wheel wheel) {
    this.wheel = wheel;
}

}

package cn.itcast.d_component;
// 车轮
public class Wheel {

private int count;
private int size;
public int getCount() {
    return count;
}
public void setCount(int count) {
    this.count = count;
}
public int getSize() {
    return size;
}
public void setSize(int size) {
    this.size = size;
}

}

<class name="Car" table="t_car">
    <id name="id">

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

    <property name="name" length="20"></property>

<!-- 组件映射 -->
<component name="wheel">
    <property name="size"></property>
    <property name="count"></property>
</component>

  </class >

package cn.itcast.d_component;

import org.hibernate.Hibernate;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.classic.Session;
import org.junit.Test;

public class App {

private static SessionFactory sf;
static {
    sf = new Configuration()
        .configure()
        .addClass(Car.class)   
        .buildSessionFactory();
}

@Test
public void getSave() {

    Session session = sf.openSession();
    session.beginTransaction();

    // 轮子
    Wheel wheel = new Wheel();
    wheel.setSize(38);
    wheel.setCount(4);
    // 汽车
    Car car = new Car();
    car.setName("BMW");
    //关系
    car.setWheel(wheel);

    // 保存   ////因为是生成到一张表,所以不用级联
    session.save(car);

    session.getTransaction().commit();
    session.close();

}

}

2、继承映射

需求:动物

猴子

package cn.itcast.e_extends2;

// 动物类
public abstract class Animal {

private int id;
private String name;


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;
}

}
package cn.itcast.e_extends2;

public class Monkey extends Animal {

// 吃香蕉
private String eatBanana;

public String getEatBanana() {
    return eatBanana;
}

public void setEatBanana(String eatBanana) {
    this.eatBanana = eatBanana;
}

}
package cn.itcast.e_extends2;

public class Cat extends Animal{

// 抓老鼠
private String catchMouse;

public String getCatchMouse() {
    return catchMouse;
}

public void setCatchMouse(String catchMouse) {
    this.catchMouse = catchMouse;
}

}

A、继承映射(配置方式一)
这里将所有子类映射到一张表 (1张表)
什么情况用?
子类教多,且子类较为简单,即只有个别属性!
好处:因为使用一个映射文件, 减少了映射文件的个数。
缺点:(不符合数据库设计原则)
一个映射文件: Animal.hbm.xml
(如何区分是哪个子类的信息?)

数据库:
T_animal (要存储所有的子类信息) “鉴别器”
Id name catchMouse eatBanana type_(区别是哪个子类)
1 大马猴 NULL 吃10个香蕉 猴子
2 大花猫 不抓老鼠 NULL 猫

<class name="Animal" table="t_animal">
<id name="id">
    <generator class="native"></generator>
</id>
    <!-- 指定鉴别器字段(区分不同的子类) --
    <discriminator column="type_"></discriminator>

    <property name="name"></property>
<!-- 
     子类:猫
      每个子类都用subclass节点映射
      注意:一定要指定鉴别器字段,否则报错!
      鉴别器字段:作用是在数据库中区别每一个子类的信息,就是一个列
        discriminator-value="cat_"
            指定鉴别器字段,即type_字段的值
            如果不指定,默认为当前子类的全名
     -->
     <subclass name="Cat" discriminator-value="cat_">
        <property name="catchMouse"></property>
     </subclass>

     <!-- 
        子类:猴子
      -->
      <subclass name="Monkey" discriminator-value="monkey_">
        <property name="eatBanana"></property>
      </subclass>

</class>

B、继承映射(配置方式二)
这里将所有类分别映射到一张表(3张表)
数据库
T_anmal (存储父类信息)
1 大花猫
T_cat (引用父类的主键)
1 抓小老鼠
T_monkey(引用父类的主键)

总结:
一个映射文件,存储所有的子类; 子类父类都对应表;
缺点:表结构比较复杂,插入一条子类信息,需要用2条sql: 往父类插入、往子类插入!

 <!-- 
继承映射, 每个类对应一张表(父类也对应表)
 -->
<class name="Animal" table="t_animal">
    <id name="id">
        <generator class="native"></generator>
    </id>
    <property name="name"></property>

    <!-- 
        子类:猫  t_cat
        key 指定_cat表的外键字段
    -->
    <joined-subclass name="Cat" table="t_cat">
        <key column="t_animal_id"></key>
        <property name="catchMouse"></property>
    </joined-subclass>

    <!-- 子类:猴子  t_monkey -->
    <joined-subclass name="Monkey" table="t_monkey">
        <key column="t_animal_id"></key>
        <property name="eatBanana"></property>
    </joined-subclass>

</class>

C、继承映射(配置方式三) 推荐使用这种配置方式!!!!!
数据库:
T_cat
Id name catchMounse
T_monkey
Id name eatBanana
总结:
所有的子类都写到一个映射文件;(2张表)
父类不对应表; 每个子类对应一张表

<!-- 
   继承映射, 每个类对应一张表(父类不对应表)
 -->
<hibernate-mapping package="cn.itcast.e_extends4">
<!-- 
     abstract="true"  指定实体类对象不对应表,即在数据库中不生成表
 -->
  <class name="Animal" abstract="true">
    <!-- 注意:如果用union-subclass节点,主键生成策略不能为自增长!!! -->
    <id name="id">
        <generator class="uuid"></generator>
    </id>
    <property name="name"></property>

    <!-- 
        子类:猫  t_cat
        union-subclass  
            table 指定为表名, 表的主键即为id列
    -->
    <union-subclass name="Cat" table="t_cat">
        <property name="catchMouse"></property>
    </union-subclass>

    <!-- 子类:猴子  t_monkey -->
    <union-subclass name="Monkey" table="t_monkey">
        <property name="eatBanana"></property>
    </union-subclass>

   </class>
 </hibernate-mapping>

////测试类(针对上面两种配置情况进行测试)
package cn.itcast.e_extends3;

import java.util.List;

import org.hibernate.Query;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.classic.Session;
import org.junit.Test;

public class App {

private static SessionFactory sf;
static {
    sf = new Configuration()
        .configure()
        .addClass(Animal.class)   
        .buildSessionFactory();
}

@Test
public void getSave() {

    Session session = sf.openSession();
    session.beginTransaction();

    // 保存
    Cat cat = new Cat();
    cat.setName("大花猫");
    cat.setCatchMouse("抓小老鼠");

    Monkey m = new Monkey();
    m.setName("猴子");
    m.setEatBanana("吃10个香蕉");

    // 保存
    session.save(cat);
    session.save(m);

    session.getTransaction().commit();
    session.close();

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值