热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

千山万水之Hibernate(八)——继承映射

类之间的关系,我们可以分为四种:关联、依赖、继承、实现。而我们所说的实体类之间的关系往往会想到两种:关联和继承,其他两种为什么会不是很常用?首先类之间的依赖是一种比较弱的关系,在代

类之间的关系,我们可以分为四种:关联、依赖、继承、实现。而我们所说的实体类之间的关系往往会想到两种:关联和继承,其他两种为什么会不是很常用?首先类之间的依赖是一种比较弱的关系,在代码上可以理解为在一个类的方法的参数上或方法内部对另一个类有引用或调用,引用类或调用类不属于原始类的变量类型,实体类之间一般不存在方法,也就谈不上依赖了。实现描述的是类与接口的关系,一般接口用于定义方法,也就是相当于定义出一些规范,不进行实现。
在前面几篇文章中,我们了解和学习了如何使用Hibernate进行实体类之间的关联映射,可以说这样的关联关系是项目中经常用到的,在项目中我们还会时常考虑到实体类继承这样的情况,今天我们就说说怎么用Hibernate来实现实体类之间的继承映射。

原理分析

Hibernate提供了三种策略以实现类的继承映射:一棵继承树一张表、一个类一张表、一个具体子类一张表。

1.一棵继承树一张表

先来看第一种策略要达到的效果:
技术分享
看我们的映射文件:



<hibernate-mapping package="com.tgb.hibernate">
    <class name="Animal" lazy="false">
        <id name="id">
            <generator class="native" />
        id>
        
        <discriminator column="type" type="string" />

        <property name="name" />
        <property name="sex" />

        
        <subclass name="Pig" discriminator-value="P">
            <property name="weight" />
        subclass>
        <subclass name="Bird" discriminator-value="B">
            <property name="height">property>
        subclass>
    class>
hibernate-mapping>

第一种方案采用subclass标签映射子类,采用discriminator鉴别器以区分子类。

2.一个类一张表

效果图如下:
技术分享

映射文件如下:



<hibernate-mapping package="com.tgb.hibernate">
    <class name="Animal" table="t_animal" lazy="false">
        <id name="id">
            <generator class="native" />
        id>

        <property name="name" />
        <property name="sex" />

        
        <joined-subclass name="Pig" table="t_pig">
            <key column="pid" />
            <property name="weight" />
        joined-subclass>

        <joined-subclass name="Bird" table="t_bird">
            <key column="bid" />
            <property name="height" />
        joined-subclass>
    class>
hibernate-mapping>

第二种方案使用joined-subclass标签来映射子类,每每看到join这个单词,就想到了SQL中的连接查询,此处亦有异曲同工之妙呀。

3.一个具体子类一张表

效果图如下:
技术分享
映射文件如下:



<hibernate-mapping package="com.tgb.hibernate">
    <class name="Animal" table="t_animal" abstract="true">
        <id name="id">
            <generator class="assigned" />
        id>

        <property name="name" />
        <property name="sex" />

        
        <union-subclass name="Pig" table="t_pig">
            <property name="weight" />
        union-subclass>

        <union-subclass name="Bird" table="t_bird">
            <property name="height" />
        union-subclass>
    class>
hibernate-mapping>

第三种方案使用union-subclass标签关联子类进行映射,该种方式将父类的属性联合添加到子类中,映射到表字段,也就是说,多个子类表中有相同的字段结构。

对比

三种实现策略中,第一种策略,表结构有冗余字段,不符合基本的三范式要求,但查询效率较高;第二种策略,存储清晰,子类对应表只存放扩展属性,但如果继承层次比较深,查询时关联的表也会很多;第三种策略不适合使用主键递增的策略方式。
三种方式有好有坏,只能借助经验和具体需求来选定使用哪一种策略。

操作示例

在了解了继承映射的实现原理之后,我们可以接触一个新的概念——多态查询:hibernate在加载数据的时候,能够采用instanceof能够鉴别出真正的类型。而Load在默认情况下是不支持多态查询的。
示例代码如下:
保存数据方法:

public void SaveAnimal(){
        Session session = null;
        Transaction tx = null;
        try{
            session = HibernateUtils.getSession();
            tx = session.beginTransaction();

            Pig pig = new Pig();
            pig.setName("pig1");
            pig.setSex(false);
            pig.setWeight(200);
            session.save(pig);

            Bird bird = new Bird();
            bird.setName("bird1");
            bird.setSex(true);
            bird.setHeight(100);
            session.save(bird);

            tx.commit();
        }catch(Exception e){
            e.printStackTrace();
            if(tx != null){
                tx.rollback();
            }
        }finally{
            HibernateUtils.closeSession(session);
        }
    }

测试多态查询示例如下:

public void testLoad(){
        Session session = null;
        Transaction tx = null;
        try{
            session = HibernateUtils.getSession();
            tx = session.beginTransaction();

            Animal animal = (Animal)session.load(Animal.class, 1);
            if(animal instanceof Pig){
                System.out.println(animal.getName());
            }

            tx.commit();
        }catch(Exception e){
            e.printStackTrace();
            if(tx != null){
                tx.rollback();
            }
        }finally{
            HibernateUtils.closeSession(session);
        }
    }

此方法在默认的配置下将不打印任何内容。
我们将映射文件Animal的class标签属性lazy设置为”false”,控制台将打印动物名。

总结

至此,Hibernate中的继承映射介绍完了,讲这么半天,其实是在做一件事,那就是如何将继承式的对象模型对应到数据库存储及其之后的读取、修改等操作。Hibernate为我们提供了很多方案,在实际项目中,按照具体情况(存储数据的数量级、继承层次、效率要求等),选取较为合适的策略。有了技术基础,就是经验、思想了。

千山万水之Hibernate(八)——继承映射


推荐阅读
  • 在Python编程中,探讨了并发与并行的概念及其区别。并发指的是系统同时处理多个任务的能力,而并行则指在同一时间点上并行执行多个任务。文章详细解析了阻塞与非阻塞操作、同步与异步编程模型,以及IO多路复用技术的应用。通过模拟socket发送HTTP请求的过程,展示了如何创建连接、发送数据和接收响应,并强调了默认情况下socket的阻塞特性。此外,还介绍了如何利用这些技术优化网络通信性能和提高程序效率。 ... [详细]
  • 在BZOJ 2563中,阿狸与桃子进行了一场策略博弈游戏。该问题的时间限制为3秒,内存限制为128MB,目前已有97次提交记录。通过对游戏规则和策略的深入分析,本文探讨了双方在不同情况下的最优决策路径,并提出了高效的算法解决方案。 ... [详细]
  • 在基于.NET框架的分层架构实践中,为了实现各层之间的松散耦合,本文详细探讨了依赖注入(DI)和控制反转(IoC)容器的设计与实现。通过合理的依赖管理和对象创建,确保了各层之间的单向调用关系,从而提高了系统的可维护性和扩展性。此外,文章还介绍了几种常见的IoC容器实现方式及其应用场景,为开发者提供了实用的参考。 ... [详细]
  • 在多堆石子游戏中,通过分析Nim博弈策略,探讨了如何在限定时间和内存条件下实现最优解。本文详细研究了石子游戏中的数学原理和算法优化方法,旨在为参与者提供有效的策略指导。具体而言,文章讨论了不同堆数下的Nim值计算及其应用,帮助玩家在复杂的博弈环境中取得优势。 ... [详细]
  • C#中实现高效UDP数据传输技术
    C#中实现高效UDP数据传输技术 ... [详细]
  • 为了在Fragment中直接调用Activity的方法,可以通过定义一个接口并让Activity实现该接口来实现。具体步骤包括:首先在Fragment中声明一个接口,并在Activity中实现该接口。接着,在Fragment中通过类型转换检查Activity是否实现了该接口,如果实现了则调用相应的方法。这种方法不仅提高了代码的解耦性,还增强了模块间的通信效率。此外,还可以通过ViewModel或LiveData等现代Android架构组件进一步优化这一过程,以实现更加高效和可靠的通信机制。 ... [详细]
  • 深入解析 OpenCV 2 中 Mat 对象的类型、深度与步长属性
    在OpenCV 2中,`Mat`类作为核心组件,对于图像处理至关重要。本文将深入探讨`Mat`对象的类型、深度与步长属性,这些属性是理解和优化图像操作的基础。通过具体示例,我们将展示如何利用这些属性实现高效的图像缩小功能。此外,还将讨论这些属性在实际应用中的重要性和常见误区,帮助读者更好地掌握`Mat`类的使用方法。 ... [详细]
  • 本研究提出了一种方法,用于判断两个数组中的元素是否相同,而不考虑其顺序。该方法通过检查数组中每个元素的出现次数来实现。具体实现如下:首先验证输入参数是否为数组,然后对两个数组进行排序并逐个比较元素。若所有元素均相等,则返回 `true`,否则返回 `false`。此方法适用于需要忽略顺序的数组比较场景。 ... [详细]
  • 题目链接:http://poj.org/problem?id=3083。题目描述:给定一个迷宫,其中 'S' 表示起点,'E' 表示终点,'#' 表示墙壁,'.' 表示可通行的道路。起点和终点均位于迷宫的边界上,并且保证存在唯一路径。任务是求从起点 'S' 到终点 'E' 的最短路径步数,且优先考虑向左转弯。通过深度优先搜索(DFS)和广度优先搜索(BFS)算法进行路径探索,分析两种方法的优劣及适用场景。 ... [详细]
  • 本文深入解析了线程事件机制的原理及其在实际应用中的案例。通过具体示例,展示了多个线程在不同状态下的交互过程,如线程1、2、3处于等待连接状态,而线程4则负责检测服务的运行状况,并在检测完成后通知其他线程开始连接。该机制有效提高了多线程环境下的资源利用效率和系统响应速度。 ... [详细]
  • ASP11:深入解析与应用展望本文详细探讨了 ASP11 中的 `AppRelativeTemplateSourceDirectory` 属性,该属性用于获取或设置包含控件的 Page 或 UserControl 对象的应用程序相对虚拟目录。此外,文章还介绍了 1.0 版本中的 Binding 机制,分析了其在实际开发中的应用和优化方法,为开发者提供了全面的技术指导。 ... [详细]
  • C++ STL 常见函数应用详解与实例解析
    本文详细解析了 C++ STL 中常见函数的应用,并通过具体实例进行说明。特别地,文章对迭代器(iterator)的概念进行了深入探讨,将其视为一种将迭代操作抽象化的工具,便于在不同容器间进行元素访问和操作。此外,还介绍了迭代器的基本类型、使用方法及其在算法中的应用,为读者提供了丰富的实践指导。 ... [详细]
  • Spring Batch 异常处理与任务限制优化策略 ... [详细]
  • Git基础操作指南:掌握必备技能
    掌握 Git 基础操作是每个开发者必备的技能。本文详细介绍了 Git 的基本命令和使用方法,包括初始化仓库、配置用户信息、添加文件、提交更改以及查看版本历史等关键步骤。通过这些操作,读者可以快速上手并高效管理代码版本。例如,使用 `git config --global user.name` 和 `git config --global user.email` 来设置全局用户名和邮箱,确保每次提交时都能正确标识提交者信息。 ... [详细]
  • 通过优化模板消息机制,本研究提出了一种高效的信息化推送方案。该方案利用获取的访问令牌(access token)和指定的模板ID,实现了精准且快速的信息推送,显著提升了用户体验和信息传递效率。具体实现中,通过调用相关API接口,确保了消息的准确性和及时性,为用户提供更加便捷的服务。 ... [详细]
author-avatar
娟紫恋蓝_610
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有