首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

单表继承-附加类名

单表继承(Single Table Inheritance)是一种ORM(对象关系映射)设计模式,它在一个数据库表中存储所有继承层次结构的实体。在这种模式下,每个具体的子类都会在同一个表中拥有自己的字段,同时还有一个字段用来区分不同的子类类型。这个用来区分类型的字段通常被称为“类型标识符”或“discriminator”。

基础概念

附加类名通常指的是在单表继承中,用于区分不同子类的字段,这个字段的值通常是子类的名称或者一个代表该子类的唯一标识。

优势

  1. 查询效率高:由于所有数据都在同一张表中,因此查询时不需要进行表连接操作。
  2. 简化数据库结构:减少了表的数量,简化了数据库的设计和管理。

类型

  • 具体表继承:每个具体的子类都有自己的表,但共享一个基类表。
  • 单表继承:所有子类都存储在同一个表中。
  • 类表继承:每个类(包括基类和子类)都有自己的表。

应用场景

  • 当继承层次结构不是很深,且子类之间的差异不大时。
  • 当需要频繁地查询整个继承层次结构的数据时。
  • 当希望简化数据库模型,减少表的数量时。

遇到的问题及原因

问题:在使用单表继承时,可能会遇到字段冗余、更新异常等问题。

原因

  • 字段冗余:如果基类和子类都有相同的字段,那么这些字段会在表中重复出现。
  • 更新异常:当基类的字段发生变化时,可能需要同时更新所有子类的对应字段。

解决方法

  1. 合理设计继承结构:避免不必要的字段重复,确保每个子类都有其独特的字段。
  2. 使用数据库触发器:在基类字段更新时,通过触发器自动更新所有子类的对应字段。
  3. 使用ORM框架的特性:许多ORM框架提供了对单表继承的内置支持,可以利用这些特性来简化开发和维护。

示例代码(以Python的SQLAlchemy为例)

代码语言:txt
复制
from sqlalchemy import Column, Integer, String, create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker

Base = declarative_base()

class Animal(Base):
    __tablename__ = 'animals'
    id = Column(Integer, primary_key=True)
    type = Column(String(50))  # Discriminator column
    name = Column(String(50))

class Dog(Animal):
    __mapper_args__ = {
        'polymorphic_identity': 'dog',
    }
    breed = Column(String(50))

class Cat(Animal):
    __mapper_args__ = {
        'polymorphic_identity': 'cat',
    }
    color = Column(String(50))

engine = create_engine('sqlite:///:memory:')
Base.metadata.create_all(engine)

Session = sessionmaker(bind=engine)
session = Session()

# Adding records
dog = Dog(name='Buddy', breed='Golden Retriever')
cat = Cat(name='Whiskers', color='Black')
session.add_all([dog, cat])
session.commit()

# Querying records
animals = session.query(Animal).all()
for animal in animals:
    if isinstance(animal, Dog):
        print(f'Dog: {animal.name}, Breed: {animal.breed}')
    elif isinstance(animal, Cat):
        print(f'Cat: {animal.name}, Color: {animal.color}')

在这个例子中,type字段就是附加类名,用于区分不同的动物类型。通过设置__mapper_args__中的polymorphic_identity,SQLAlchemy知道如何将数据库中的记录映射到正确的类实例。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

在NHibernate的单表继承模式下通过父类Repository查询子类

.html)介绍了有3种常用的实现方式: Concrete Table Inheritance(具体表继承) Single Table Inheritance(单表继承) Class Table Inheritance...(类表继承) 其中单表继承是我个人比较常用比较推荐的做法。...使用单表继承可以不用Join多个表查询效率高,而且在Domain Model的属性提示到父类或者下降到子类时,数据库模型不用更改。...在NHibernate中经常会遇到通过父类的Repository来查询子类的情况,比如现在有一个抽象的Employee对象,下面有OfficeUser和Teacher两个具体的对象,这两个对象都有其特有的属性...以上是以最简单了例子说明了如果通过父类查询具体的子类的方法,实际项目中肯定比这个查询要复杂,但是只要记住了这三种查询的要点,结合其他条件就可以写出NHibernate能够理解的查询。

35820
  • Python 在子类中调用父类方法详解(单继承、多层继承、多重继承)

    测试环境: win7 64位 Python版本:Python 3.3.5 代码实践: 1、在子类中通过“类名”调用父类的方法 class FatherA: def __init__(self)...__init__(self) # 在子类中调用父类的方法:父类名.方法名称(参数) if __name__ == '__main__': b = SubClassB() 运行结果: >>> ==...(如类SubClassB的父类由FatherA变为FatherD时),必须遍历整个类定义,把子类中所有的父类类名全部替换过来 2、在子类中通过“super”方法调用父类的方法 场景1、单层继承 class...-type的父类(如果有的话),即type决定了前往哪个父类调用指定的方法 场景3、多重继承 实验1: class FatherA: def __init__(self): print('init...,以super().method(参数)方法调用父类的方法,如果不同父类中存在同名方法method(不管参数列表是否相同),则按继承顺序,选择第一个父类中的方法。

    3.2K30

    【C++】继承 ① ( 面向对象特点 | 类之间的关系 | 单继承与多继承 | 继承关系特性 )

    ; IS-A 类关系 : 类的继承 , 接口实现 ; 泛化关系 Generalization : 一般描述 和 具体描述 之间的关系 , 继承中的 父类 和 子类 就是这种关系 ; 实现关系...继承 是两个类之间的关系 ; 在C++中,使用 : 运算符来实现继承 ; A 类 是 父类 , B 类 是 子类 ; B 类 继承 A 类 , A 类 派生 B 类 ; 父类 又称为 基类 ; 子类...又称为 派生类 ; 2、单继承与多继承 单继承 与 多继承 : A 类 只有一个 子类 B 类 , 那么 该继承 就是 单继承 ; A 类 有多个子类 B1 类 , B2 类 … , 该 继承 是 多继承...; 单继承 单继承是指一个类只能继承一个父类的特性和行为 ; 下面的代码中 , Child 类继承了 Parent 类的所有公有和保护成员 , 并且可以访问它们 ; 注意 : Child 类不能继承...}; 多继承 多继承是指一个类可以继承多个父类的特性和行为 ; 下面的代码中 , Child 类继承了 Parent1 和 Parent2 类的所有 公有 和 保护 成员 , 并且可以访问它们 ; 注意

    21930

    面向对象编程-继承1.继承介绍以及单继承2.继承示例3.多继承4.重写父类方法与调用父类方法5.类属性和实例属性6.静态方法和类方法

    1.继承介绍以及单继承 将共性的内容放在父类中,子类只需要关注自己特有的内容 继承的概念:在现实生活中,继承一般指的是子女继承父辈的财产,在程序中,继承描述的是事物之间的所属关系,例如猫和狗都属于动物...2.继承示例 1.定义一个父类: ? 2.定义一个子类: ? 3.运行结果: ?...说明:虽然子类没有定义__init__方法,但是父类有,所以在子类继承父类的时候这个方法就被继承了,所以只要创建Bosi的对象,就默认执行了那个继承过来的__init__方法 总结:子类在继承的时候,在定义类时...,小括号()中为父类的名字 ·父类的属性、方法,会被继承给子类 ?...说明:python中是可以多继承的,在java中叫接口           父类中的方法、属性,子类会继承 2.如果父类A和父类B中,有一个同名的方法,那么通过子类去调用的时候,调用哪个? ?

    1.2K20

    【SSH快速进阶】——Hibernate继承映射:每个类映射一张表

    https://blog.csdn.net/huyuyang6688/article/details/50689003   上文说了每棵继承树映射一张表,本文继续描述让每个类都映射一张表的配置...上图中Pig类和Bird类继承Animal类,要让每个类映射一张表,就是让着三个类都分别映射一张表,但同时这三张表也跟对应的三个类似的,有继承关系,在父类对应的表中,实际上会存储所有子类对应的记录,如下表所示...所以对对象的操作同上篇文章《【SSH快速进阶】——Hibernate继承映射:每棵继承树映射一张表》中的测试一致。...在表1中就可以看出,父类是真正意义上的“父类”,因此,如果父类是抽象类或者没有实际意义的话,可以用此方案。...---- 【 转载请注明出处——胡玉洋《【SSH快速进阶】——Hibernate继承映射:每个类映射一张表》】

    40630

    ORM中的继承关系映射全解——单表继承体系、一实体一具体表、一实体一扩展表、接口映射

    一实体一扩展表 4. 接口实现映射vs基类继承映射 1. 单表继承体系 所谓单表继承体系就是用一张数据库表存储整个继承体系中的所有实体的数据。...单表继承体系适合那种继承体系中实体数目相对较少,总记录数相对较少,子类对父类的属性扩展也相对较少的情形。 ...单表继承体系优点是读/写继承体系中的每个实体的数据,都只需操作一张表,性能较好,并且,新增继承类,或扩展实体属性都只需要增减一张表的字段就可以了,易于维护;主要缺点是,因为所有的实体共享一张表,表中会有比较多的...但是,以这样的简单方式定义单表继承时,因为从表中读数据时无法知道一行数据真正对应的是哪一个子类,所以,实际情况下,一般我们都要附加一些查询条件和字段默认值。 ...带附加条件的单表继承体系 采用单表继承体系方案时,继承体系中的不同子类不仅仅扩展父类的属性,肯定还会附带一些字段查询条件和默认值。

    2.5K90

    【SSH快速进阶】——Hibernate继承映射:每个具体类映射一张表

    上图中Pig类和Bird类继承Animal类,要让每个具体类映射一张表,就是只映射Pig和Bird,如下表所示:                        (表 1) ?   ...标签来定义即可;用标签定义两个子类,且每个类对应的表的信息是完全的,包含了所有从父类继承下来的属性。...:每棵继承树映射一张表》中的测试一致。   ...如果追求细粒度的设计且子类数量不多,则可以用后两种方案:每个类映射一张表或每个具体类映射一张表。...---- 【 转载请注明出处——胡玉洋《【SSH快速进阶】——Hibernate继承映射:每个具体类映射一张表》】

    44640

    【Python】面向对象 - 继承 ② ( 子类重写父类成员 | 子类调用父类重名成员 | 子类中使用 父类类名 调用父类成员 | 子类中使用 super 调用父类成员 )

    一、子类重写父类成员 1、子类重写父类成员语法 子类 继承 父类的 成员属性 与 成员方法 后 , 如果对 继承的 父类成员 不满意 , 可以 重写 父类成员 ; 成员 属性 和 成员 方法 , 都可以进行重写...访问父类成员 : 如果需要调用被重写之前的 父类成员 , 则需要使用如下方法 : 方法一 : 使用 父类类名 调用父类成员 ; 调用父类同名成员变量 : 父类类名.成员变量名 调用父类同名成员方法...: 父类类名.成员方法名(self) 方法二 : 使用 super 调用父类成员 ; 调用父类同名成员变量 : super().成员变量名 调用父类同名成员方法 : super().成员方法名(...) 2、代码示例 - 子类中使用 父类类名 调用父类成员 在 Dog 子类中的 make_sound 函数中 , 通过 Animal.name 和 Animal.age 可以调用父类的成员变量 , 打印出来的值为父类的成员变量值...; 通过 Animal.make_sound(self) 可以调用父类的 成员方法 ; 注意 : 调用 父类 成员方法时 , 需要带参数 self ; 完整代码示例 : """ 面向对象 - 继承 "

    75530

    在CMD窗口中使用javac和java命令进行编译和执行带有包名的具有继承关系的类

    一、背景   最近在使用记事本编写带有包名并且有继承关系的java代码并运行时发现出现了很多错误,经过努力一一被解决,今天我们来看一下会遇见哪些问题,并给出解决办法。...解决办法为:我们需要使用javac *.java命令来进行运行,因为此时存在继承关系,编译子类的同时也需要先编译父类 2)运行java Zi命令,出现以下错误 ? 这是什么原因呢?...因为我们在编写程序时用到了包名,所以运行类文件时,需要完整名称,命令修改为:java com.hafiz.zhang.Zi 我们会发现出现以下错误 ?...由此我们得出了在CMD窗口中使用javac和java命令进行编译和执行带有包名的具有继承关系的类的方式: 1.使用javac -d . *.java进行编译 2.使用java com.hafiz.Zi(...带包名的类全名)命令进行运行!

    1.6K40

    PHP常见面试题_php算法面试题及答案

    PHP的基础知识点 PHP中类的继承属于单继承,一个子类只能继承一个父类。可见性为public protected的属性和方法可以被继承。 继承的方法或属性可以被重写,可见性越来越大。...PHP中的变量名区分大小写,但类名、函数名不区分大小写。...MyISAM的每个数据表包括三个文件,分别是表的结构、表的索引和表的数据,表的索引和表的数据是分开存储的。 InnoDB在写操作比较多的时候会更优秀,InnoDB支持事务、外键和行锁。...InnoDB的数据表包括两个文件,表的索引和数据存储在同一个文件中,默认是共享表空间,即所有数据表的索引和数据存储在同一个文件中,但也可以设置为独立表空间(若要对数据表采用分区技术,必须设置为独立表空间...get是表单的默认提交方式,会把数据附加到表单的action属性所指向的URL中,在URL中可见,安全性较差;post会把数据放到http的包体中,用户一般看不到,安全性较好。

    1.3K20

    《封装、继承与多态》问题一:封装只有类能做吗?结构体如何封装?名空间、文件能实现封装吗?还有没有其他方式?

    问题一:封装只有类能做吗?结构体如何封装?名空间、文件能实现封装吗?还有没有其他方式?...在实际开发中,封装不仅限于类,还可以通过结构体、命名空间、文件甚至其他设计方式实现。以下是详细的说明与举例: 1. 类实现封装 类是封装的最常用工具。...facade; facade.unifiedOperation(); return 0; } 总结表格:封装实现方式对比 序号 实现方式 优势 场景适用 类比示例 1 高度封装 支持多态和继承...面向对象编程的核心工具,适用于需要复杂对象模型和继承体系的场景。 C++中的类和对象 2 结构体 简洁轻量,适用于简单数据封装,不需要复杂的继承和多态。...需要抽象出通用接口或简化复杂子系统的场景,如工厂模式、单例模式等。 软件工程中的设计模式

    8410
    领券