继承关系在内存和DB中的映射

  • 使用

    • 将若干相似的类映射为单表,对拥有许多特殊数据的类使用具体表继承.

    • 对高层次使用类表继承,对低层次使用具体表继承.

  • Single Table Inheritance
    • 在DB中将类继承层次设计为一个单表,表中各列代表不同类中的所有域.

    • 运行机制
      • 每个类负责把与之相关的数据保存在表的一行中.表中其它不相关的列留空.

      • 通过表中的Type字段来决定向内存中加载对象时,应该实例化那个类来创建该对象.
        • 可以直接使用类名称

        • 或者需要经过翻译的Code域.

      • 保存数据的代码可以由层超类负责.

    • 使用时机
      • 优点
        • 只需要关注一个DB表.

        • 获取数据时不必进行连接.

        • 对继承层次的重构(在父子之间挪动某个域)不需要修改DB.

      • 缺点
        • DB表的列和对象的域不是一一对应的.

        • 空间的浪费.

        • 可能太大的单表.过多的索引被频繁上锁.导致访问效率低下.

        • 域名称可能重复(加上类名做区分可以解决).

  • Class Table Inheritance
    • 每个DB来代表一个类.

    • 运行机制
      • 类中的域直接映射到相应表中的字段上.

      • 表的行链接问题
        • 使用公用的主键.由于超类表针对其它子类表中的每一行都有对应的一行.所以主键必须在各表间唯一.

        • 每个表都有自己的主键,并使用超类表的外键把各行联系在一起.

      • 最大的问题是如何有效地把数据从多个表中取回.
        • 对每个表都进行一次调用会造成多次调用.

        • 一次链接来处理多个表,会在表数目较大时,产生性能问题.

      • 通常,对于指定的查询,并不清楚具体需要链接那些表.如查询一组运动员.
        • 使用外链接来在某些表没有数据时有效地进行链接.

        • 先读根表,然后找出下一个该读取的表.但是这样会有多次查询.

    • 使用时机
      • 优点
        • DB表更容易理解,且没有空间浪费.

        • 领域模型和DB之间的关系简单明了.

      • 缺陷
        • 加载一个对象需要访问多个表(也就是需要链接)

        • 字段在继承层次中上下移动会导致DB重构.

        • 对超类的频繁访问会导致瓶颈.

  • Concrete Table Inheritance
    • 内存中的每一个具体类对应一个DB表.


    • 运行机制
      • Db表中的列包含着具体类和其所有祖先类中的所有域.超类中的所有域在子类的DB表中都会被复制.

      • 需要保证键在继承层次中所有的表键都是唯一的.
        • 需要一个键分配系统来记录表间键的使用情况.

        • 要么避免使用超类的域,要么使用包含表ID的复合键.

      • 引用完整性问题
        • 例如,慈善活动和Player的关联.由于没有Player对应的Db表.所以无法使用外键来构建链接表.

        • 此时,可以忽略引用完整性.

        • 或者,使用多链接表.DB中的每个表都有一个链接表与之对应.

    • 使用时机

      • 优点

        • 每个DB表都是自包含的,并且不含有不相关的域.

        • 具体映射器读取数据时不需要链接操作.

        • 只有在类被访问时,对应的DB表才会被访问.分散了访问负载.

      • 缺陷
        • 主键很难处理.

        • 不能把数据库关系加到抽象类中.

        • 域在继承树上移动时,须更改表定义.

        • 超类的域改变时,会有很多的子类DB表连带更改.

        • 超类上的一次查找需要检查所有表.

  • Inheritance Mapper
    • 运行机制
      • 查找方法定义在具体子类上,因为它要返回一个具体类.OO不允许改变已声明方法的返回值类型.
        • 基本行为:在DB中找到合适的行,实例化正确类型的对象(子类决定),并用来自DB的数据来加载对象.

        • 子类映射器在加载子类特有的数据后,一直向上调用它的超类方法.

      • 插入和更新
        • 都使用保存方法.可以在超类上定义接口.

        • 插入:创建一个新行,将对象中的数据用Save钩子方法保存起来.

        • 更新:值保存数据,也使用Save钩子方法.

        • 与加载类似,每个类保存其特有的数据,之后调用超类的保存方法.

      • 一个支持保存和加载的抽象类
        • Abstract Player映射器负责向DB中加载和保存特定的Player数据.
          • 它是一个抽象类.其行为只有具体的映射器子类使用.

        • 独立的Player映射器.
          • 提供了操作的接口.

          • 提供了查找方法.

          • 覆盖了插入和更新方法.

          • 其只负责找到应该处理某个具体任务的具体映射器,并把任务委托给该具体映射器.

时间: 2024-10-27 18:22:50

继承关系在内存和DB中的映射的相关文章

C++各种类继承关系的内存布局

body, table{font-family: 微软雅黑; font-size: 10pt} table{border-collapse: collapse; border: solid gray; border-width: 2px 0 2px 0;} th{border: 1px solid gray; padding: 4px; background-color: #DDD;} td{border: 1px solid gray; padding: 4px;} tr:nth-child(

【深入理解JVM】:Java类继承关系中的初始化顺序

Java类初始化的顺序经常让人犯迷糊,现在本文尝试着从JVM的角度,对Java非继承和继承关系中类的初始化顺序进行试验,尝试给出JVM角度的解释. 非继承关系中的初始化顺序 对于非继承关系,主类InitialOrderWithoutExtend中包含了静态成员变量(类变量)SampleClass 类的一个实例,普通成员变量SampleClass 类的2个实例(在程序中的顺序不一样)以及一个静态代码块,其中静态代码块中如果静态成员变量sam不为空,则改变sam的引用.main()方法中创建了2个主

Java类继承关系中的初始化顺序

Java类初始化的顺序经常让人犯迷糊,现在本文尝试着从JVM的角度,对Java非继承和继承关系中类的初始化顺序进行试验,尝试给出JVM角度的解释. 非继承关系中的初始化顺序 对于非继承关系,主类InitialOrderWithoutExtend中包含了静态成员变量(类变量)SampleClass 类的一个实例,普通成员变量SampleClass 类的2个实例(在程序中的顺序不一样)以及一个静态代码块,其中静态代码块中如果静态成员变量sam不为空,则改变sam的引用.main()方法中创建了2个主

Hibernate中的Entity类之间的继承关系之一MappedSuperclass

在hibernate中,Entity类可以继承Entity类或非Entity类.但是,关系数据库表之间不存在继承的关系.那么在Entity类之间的继承关系,在数据库表中如何表示呢? Hibernate提供了4种兼容JPA的策略,解决Entity类的继承与关系数据库表的对应不匹配问题.这里介绍第一种MappedSuperclass. 在这种策略中,存在如下特征: 只在Entity类之间存在继承关系,其中的父Entity类使用@javax.persistence.MappedSuperclass标注

由socketserver源码引出的类的继承关系

当我们拿到一份python源代码,我们要怎么去看呢? 下面我们以socketserver为例,看下面的一段代码: 1 #!/usr/bin/env python 2 # -*- coding: UTF-8 -*- 3 # Author: ZCX 4 5 import socketserver #导入socketserver模块 6 7 8 class MyServer(socketserver.BaseRequestHandler): #定义一个类 9 def handle(self): #定义

Activiti 5.17 Activiti与restlet的继承关系和扩展

Activiti5.17 使用Restlet 2.2.1 作为服务接入的前端框架. 在Activiti中,包括三个应用:activiti-modler.activiti-explorer和acriviti-rest,多个应用可以使用多个流程引擎实例. Activiti 与 restlet 的继承关系如下图: activiti中的restful service的配置完全代码化,通过 ModelerServicesInit 和 RestServicesInit 完成. 既然activiti 使用了s

Pycharm 查看一个类的继承关系图

Pycharm 查看一个类的继承关系图 在我们开发过程中: 无论是使用的开发框架自带的类, 还是我们自定义的类都特别多; 并且类之间单继承和多继承频繁使用, 这个继承,不仅仅是一级的继承关系,包括好几层的继承.父类的父类的父类. 直到最后->很难清楚一个类的实现关系, 迷失类的作用. 这里我们可以通过查看类的继承关系, 明白类的作用 查看DRF框架的APIView类的继承关系 下图就是我们查找的继承关系 查看DRF框架的GenericAPIView类所在.py模块的所有类继承关系 1.通过Ctr

《Entity Framework 6 Recipes》中文翻译系列 (9) -----第二章 实体数据建模基础之继承关系映射TPH

翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 2-10 Table per Hierarchy Inheritance 建模 问题 你有这样一张数据库表,有一类型或鉴别列.它能判断行中的数据在你的应用中代表的是什么.你想使用table per hierarchy(TPH)继承映射建模. 解决方案 让我们假设你有如图2-20中的表(译注:总感觉作者使用的图,跟实际描述对不上,比如下图应该是实体模型图),Employee表包含hourly

javascript中的对象继承关系

相信每个学习过其他语言的同学再去学习JavaScript时就会感觉到诸多的不适应, 这真是一个颠覆我们以前的编程思想的一门语言,先不要说它的各种数据类型以及表达 式的不同了,最让我们头疼,恐怕就是面向对象的部分了,在JavaScript中,是没有给定一 个创建对象的关键词的,它不像Java中一个class就可以创建一个对象,在JavaScript中, 对象是一个十分松散的的key-value对的组合,通常,我们在创建对象时,可以通过{}来直 接生成一个对象,就像我们之前所学的,对象中有属性,有行