前言
在 java 中,orm(对象关系映射)框架(如 hibernate/jpa)处理继承关系时,主要有三种继承映射策略:单表继承(single table)、连接表继承(joined table) 和 每个具体类一张表(table per class)。以下介绍它们的原理、使用方法和注意事项
博客将会介绍如何实现 java 三种继承映射的使用。希望这篇博客对unity的开发者有所帮助。
大家好,我是心疼你的一切,不定时更新unity开发技巧,觉得有用记得一键三连哦。
欢迎点赞评论哦.下面就让我们进入正文吧 !
一、单表继承(single table inheritance)
1-1、原理
所有类共享一张表:整个继承层次结构的所有字段都存储在同一张数据库表中。
鉴别器列(discriminator):使用一个特殊列(如 dtype)区分不同子类的记录。
1-2、使用方法
@entity
@inheritance(strategy = inheritancetype.single_table) // 指定策略
@discriminatorcolumn(name = "dtype") // 鉴别器列名
public class animal {
@id
private long id;
private string name;
}
@entity
@discriminatorvalue("cat") // 鉴别器值
public class cat extends animal {
private int lives;
}
@entity
@discriminatorvalue("dog")
public class dog extends animal {
private boolean canfetch;
}
表结构如下:
create table animal (
id bigint primary key,
name varchar(255),
lives integer, -- cat 的字段
canfetch boolean, -- dog 的字段
dtype varchar(10) -- 鉴别器列(值如 "cat"/"dog")
);
1-3、注意事项
优点:
查询效率高(无 join 操作)。
简单易用。缺点:
数据冗余:子类特有字段在非对应记录中为 null。
字段约束弱:非空约束(not null)无法用于子类特有字段(因为其他子类记录中这些字段为 null)。适用场景:继承层次简单、子类字段差异小、查询性能要求高的场景。
二、连接表继承(joined table inheritance)
2-1、原理
父类独立表:父类字段存储在基表中。
子类分表存储:子类特有字段存储在独立的子表中,通过主键与基表关联(一对一关系)。
2-2、使用方法
@entity
@inheritance(strategy = inheritancetype.joined) // 指定策略
public class vehicle {
@id
private long id;
private string manufacturer;
}
@entity
public class car extends vehicle {
private int seatcount;
}
@entity
public class truck extends vehicle {
private double payloadcapacity;
}
生成的表结构如下:
-- 基表(存储公共字段)
create table vehicle (
id bigint primary key,
manufacturer varchar(255)
);
-- 子表(存储特有字段 + 关联基表主键)
create table car (
id bigint primary key, -- 与 vehicle.id 相同
seatcount integer,
foreign key (id) references vehicle(id)
);
create table truck (
id bigint primary key,
payloadcapacity double,
foreign key (id) references vehicle(id)
);
2-3、注意事项
- 优点:
符合数据库范式,无冗余字段。
支持子类字段的非空约束。 - 缺点:
查询需要 join 操作,性能较低(尤其层次深时)。
插入需操作多张表。 - 适用场景:数据结构规范、子类字段差异大、对冗余敏感的场景。
三、每个具体类一张表(table per class)
3-1、原理
每个具体类独立成表:每个非抽象子类拥有一张独立的表,表中包含自身字段 + 所有继承的父类字段。
抽象父类无表:父类不映射到数据库表(仅用于 java 继承)。
3-2、使用方法
@entity
@inheritance(strategy = inheritancetype.table_per_class) // 指定策略
public abstract class shape {
@id
private long id;
private string color;
}
@entity
public class circle extends shape {
private double radius;
}
@entity
public class rectangle extends shape {
private double width;
private double height;
}
生成的表结构如下:
-- 父类 shape 无表
create table circle (
id bigint primary key,
color varchar(255), -- 继承自 shape
radius double
);
create table rectangle (
id bigint primary key,
color varchar(255), -- 继承自 shape
width double,
height double
);
3-3、注意事项
优点:
查询具体类时效率高(无需 join)。
无冗余字段。缺点:
多态查询性能差:查询父类(如 shape)需 union 所有子表。
主键生成策略需用 table 或 sequence(避免不同子表主键冲突)。适用场景:多态查询少、主要操作具体子类的场景。
四、总结对比
| 策略 | 单表继承(single_table) | 连接表继承(joined) | 每个具体类一张表(table_per_class) |
|---|---|---|---|
| 表数量 | 1 张 | n + 1 张(n=子类数) | n 张(n=具体子类数) |
| 数据冗余 | 高(大量 null) | 无 | 无 |
| 查询性能 | ⭐⭐⭐⭐⭐(无 join) | ⭐⭐(需 join) | ⭐⭐⭐(具体类快,父类慢) |
| 字段约束 | 弱(不可用 not null) | 强(支持约束) | 强(支持约束) |
| 适用场景 | 简单继承、高性能需求 | 结构规范、减少冗余 | 少用父类查询、操作具体子类 |
通用注意事项
抽象父类:若父类是抽象的,使用 @mappedsuperclass 代替 @entity(仅用于继承字段,不映射表)。
鉴别器列:单表继承必须用 @discriminatorcolumn 和 @discriminatorvalue。
多态查询:连接表继承和单表继承对多态查询支持较好。
主键策略:避免在 table_per_class 中使用 identity 主键生成(不同表主键可能冲突)。
总结
本次总结的就是 java 三种继承映射的使用实现, 有需要会继续增加功能
到此这篇关于java继承映射的三种使用方法的文章就介绍到这了,更多相关java继承映射使用内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论