Hibernate 每个类一张表策略详解

发布于:2025-07-03 ⋅ 阅读:(17) ⋅ 点赞:(0)

Hibernate 的 Table Per Class(每个类一张表) 是继承映射策略之一,适用于面向对象的继承关系在关系型数据库中的实现。其核心思想是:为继承体系中的每一个具体子类单独创建一张数据库表,父类的属性会冗余存储在每个子类表中。以下是详细解析:


📌 一、核心机制

  1. 表结构设计

    • 父类(抽象或非抽象)不生成对应的表,其属性会被复制到所有子类表中。
    • 每个子类(包括具体子类和中间抽象类)对应一张独立的表,表中包含自身属性和继承的父类属性。
  2. 主键生成
    所有子类表使用相同的主键列名和值,确保通过父类 ID 能跨表关联数据(需配合 @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) 注解)。

  3. 查询逻辑

    • 查询父类时,Hibernate 会执行 UNION ALL 合并所有子类表数据(性能较低);
    • 查询具体子类时,直接操作对应单表,效率较高 。

⚡ 二、使用示例

// 父类(不生成表)
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
@MappedSuperclass
public abstract class Animal {
    @Id @GeneratedValue
    private Long id;
    private String name;
    // getters/setters
}

// 子类1(生成独立表)
@Entity
@Table(name = "cat")
public class Cat extends Animal {
    private int whiskerLength;
    // getters/setters
}

// 子类2(生成独立表)
@Entity
@Table(name = "dog")
public class Dog extends Animal {
    private String barkVolume;
    // getters/setters
}

生成的表结构

  • cat 表:含 id(主键)、name(继承)、whisker_length(自身)
  • dog 表:含 id(主键)、name(继承)、bark_volume(自身)

⚖️ 三、优缺点对比

优点 缺点
✅ 符合直观设计,子类数据独立存储 ❌ 父类属性冗余存储,浪费空间
✅ 支持多态查询(需用 UNION ❌ 父类查询性能差(全表扫描)
✅ 子类表可单独优化索引/约束 ❌ 无法通过外键约束保证数据一致性

🔍 四、适用场景

  1. 子类差异大:子类有大量独有属性,且父类属性较少(冗余成本低)。
  2. 高频查询子类:业务主要操作具体子类,避免父类查询的 UNION 开销 。
  3. 遗留数据库适配:需映射已存在的“每个类对应表”的数据库设计 。

💡 五、与其他策略对比

策略 Table Per Class Single Table Joined Table
表数量 子类数量(父类无表) 1(所有类共用) 父类+子类各1表
查询性能 子类快,父类慢 最快(无连接) 最慢(多表连接)
数据冗余 父类属性冗余 所有字段可能冗余 无冗余

建议:优先测试 Joined TableSingle Table,仅在明确需要子表隔离时选择 Table Per Class


网站公告

今日签到

点亮在社区的每一天
去签到