一 项目准备

新建项目, 起名 inherit
cubaa

在 global 层建好 A, B, C 三个实体, 其中 B 和 C 继承 A, 如下:

A.kt

@Table(name = "INHERIT_A")
@Entity(name = "inherit_A")
open class A : StandardEntity() {
    companion object {
        private const val serialVersionUID = 2490051969193359463L
    }
    @Column(name = "A_VALUE")
    var aValue: Int? = null
}

B.kt

@Table(name = "INHERIT_B")
@Entity(name = "inherit_B")
open class B : A() {
    companion object {
        private const val serialVersionUID = 8001568716900684160L
    }
    @Column(name = "B_VALUE")
    var bValue: Int? = null
}

C.kt

@Table(name = "INHERIT_C")
@Entity(name = "inherit_C")
open class C : A() {
    companion object {
        private const val serialVersionUID = 4481159091960932193L
    }
    @Column(name = "C_VALUE")
    var cValue: Int? = null
}

cuba 的继承策略默认在父类上定义, 如果不显式定义的话默认是单表策略

二 简单继承关系探究

1. SINGLE_TABLE

上述实体建立后创建表的话默认就是 SINGLE_TABLE 策略, 生成的 DDL 如下:

-- begin INHERIT_A
create table INHERIT_A (
    ID varchar(32),
    VERSION integer not null,
    CREATE_TS datetime(3),
    CREATED_BY varchar(50),
    UPDATE_TS datetime(3),
    UPDATED_BY varchar(50),
    DELETE_TS datetime(3),
    DELETED_BY varchar(50),
    DTYPE varchar(31),
    --
    A_VALUE integer,
    --
    -- from inherit_C
    C_VALUE integer,
    --
    -- from inherit_B
    B_VALUE integer,
    --
    primary key (ID)
)^
-- end INHERIT_A

显式指定单表策略只需要在 A 类上加 @Inheritance(strategy = InheritanceType.SINGLE_TABLE)

生成的 DDL 是一样的

很显然, 结论是:

  • 三个实体只会存到同一张表中
  • 如果主键使用的是自增 ID, 将会出现单个类型的实体的 ID 不连续的问题

2. JOINED

JOINED 策略只需要在 A 类上添加 @Inheritance(strategy = InheritanceType.JOINED)

此策略生成的 DDL 如下

-- begin INHERIT_A
create table INHERIT_A (
    ID varchar(32),
    VERSION integer not null,
    CREATE_TS datetime(3),
    CREATED_BY varchar(50),
    UPDATE_TS datetime(3),
    UPDATED_BY varchar(50),
    DELETE_TS datetime(3),
    DELETED_BY varchar(50),
    DTYPE varchar(31),
    --
    A_VALUE integer,
    --
    primary key (ID)
)^
-- end INHERIT_A
-- begin INHERIT_B
create table INHERIT_B (
    ID varchar(32),
    --
    B_VALUE integer,
    --
    primary key (ID)
)^
-- end INHERIT_B
-- begin INHERIT_C
create table INHERIT_C (
    ID varchar(32),
    --
    C_VALUE integer,
    --
    primary key (ID)
)^
-- end INHERIT_C

建好 A, B, C 三个实体的 Browser 与 Editor 页面, 并三者分别添加一条记录
查看数据库如下:
A表

B表

C表

A 实体页面:
ABrowser

可得结论: JOINED 策略中:

  • 三个实体分别存到三个表中, 其中公共的属性存在父实体表中, 特有属性存在自己表中
  • 父实体与子实体的表之间通过主键关联
  • 对子实体的查询其实是通过 父 JOIN 子 的形式查出完整数据
  • 同样会出现同单个类型的实体的 ID 不连续的问题

3. TABLE_PER_CLASS

TABLE_PER_CLASS 策略只需要在 A 类上添加 @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)

生成的 DDL 如下:

-- begin INHERIT_A
create table INHERIT_A (
    ID varchar(32),
    VERSION integer not null,
    CREATE_TS datetime(3),
    CREATED_BY varchar(50),
    UPDATE_TS datetime(3),
    UPDATED_BY varchar(50),
    DELETE_TS datetime(3),
    DELETED_BY varchar(50),
    --
    A_VALUE integer,
    --
    primary key (ID)
)^
-- end INHERIT_A
-- begin INHERIT_B
create table INHERIT_B (
    ID varchar(32),
    VERSION integer not null,
    CREATE_TS datetime(3),
    CREATED_BY varchar(50),
    UPDATE_TS datetime(3),
    UPDATED_BY varchar(50),
    DELETE_TS datetime(3),
    DELETED_BY varchar(50),
    A_VALUE integer,
    --
    B_VALUE integer,
    --
    primary key (ID)
)^
-- end INHERIT_B
-- begin INHERIT_C
create table INHERIT_C (
    ID varchar(32),
    VERSION integer not null,
    CREATE_TS datetime(3),
    CREATED_BY varchar(50),
    UPDATE_TS datetime(3),
    UPDATED_BY varchar(50),
    DELETE_TS datetime(3),
    DELETED_BY varchar(50),
    A_VALUE integer,
    --
    C_VALUE integer,
    --
    primary key (ID)
)^
-- end INHERIT_C

如同名字一样, 此策略对每个实体单独创建一张完整数据的表

同样在页面上对每个实体都新增一条记录, 数据库结果:
A表

B表

C表

A 实体页面:
ABrowser

可见页面上还是能体现出实体间的父子关系, 而在数据库表中三者间的数据已经互不耦合了

TABLE_PER_CLASS 结论如下:

  • 三个实体的完整数据分别存到三个独立完整的表中
  • 父实体与子实体的表之间无关联
  • 对子实体的查询是独立的
  • 不会出现同单个类型的实体的 ID 不连续的问题

复合继承关系探究

1. 普通复合关系

如果是如下关系, 那 CUBA 将会如何生成 DDL 呢

复合的关系

生成的 DDL 如下:

-- begin INHERIT_A
create table INHERIT_A (
    ID varchar(32),
    VERSION integer not null,
    CREATE_TS datetime(3),
    CREATED_BY varchar(50),
    UPDATE_TS datetime(3),
    UPDATED_BY varchar(50),
    DELETE_TS datetime(3),
    DELETED_BY varchar(50),
    --
    A_VALUE integer,
    --
    primary key (ID)
)^
-- end INHERIT_A
-- begin INHERIT_B
create table INHERIT_B (
    ID varchar(32),
    VERSION integer not null,
    CREATE_TS datetime(3),
    CREATED_BY varchar(50),
    UPDATE_TS datetime(3),
    UPDATED_BY varchar(50),
    DELETE_TS datetime(3),
    DELETED_BY varchar(50),
    A_VALUE integer,
    --
    B_VALUE integer,
    --
    primary key (ID)
)^
-- end INHERIT_B
-- begin INHERIT_C
create table INHERIT_C (
    ID varchar(32),
    --
    C_VALUE integer,
    --
    primary key (ID)
)^
-- end INHERIT_C
-- begin INHERIT_E
create table INHERIT_E (
    ID varchar(32),
    --
    E_VALUE integer,
    --
    primary key (ID)
)^
-- end INHERIT_E
-- begin INHERIT_D
create table INHERIT_D (
    ID varchar(32),
    --
    D_VALUE integer,
    --
    primary key (ID)
)^
-- end INHERIT_D

然而在启动项目的时候报错了:
ERROR

2. 隔代复合关系

如果是如下关系又会怎么样呢
隔代复合的关系

生成的 DDL 如下:

-- begin INHERIT_A
create table INHERIT_A (
    ID varchar(32),
    VERSION integer not null,
    CREATE_TS datetime(3),
    CREATED_BY varchar(50),
    UPDATE_TS datetime(3),
    UPDATED_BY varchar(50),
    DELETE_TS datetime(3),
    DELETED_BY varchar(50),
    --
    A_VALUE integer,
    --
    primary key (ID)
)^
-- end INHERIT_A
-- begin INHERIT_B
create table INHERIT_B (
    ID varchar(32),
    VERSION integer not null,
    CREATE_TS datetime(3),
    CREATED_BY varchar(50),
    UPDATE_TS datetime(3),
    UPDATED_BY varchar(50),
    DELETE_TS datetime(3),
    DELETED_BY varchar(50),
    A_VALUE integer,
    --
    B_VALUE integer,
    --
    primary key (ID)
)^
-- end INHERIT_B
-- begin INHERIT_C
create table INHERIT_C (
    ID varchar(32),
    --
    C_VALUE integer,
    --
    primary key (ID)
)^
-- end INHERIT_C
-- begin INHERIT_E
create table INHERIT_E (
    ID varchar(32),
    --
    E_VALUE integer,
    --
    primary key (ID)
)^
-- end INHERIT_E
-- begin INHERIT_D
create table INHERIT_D (
    ID varchar(32),
    VERSION integer not null,
    CREATE_TS datetime(3),
    CREATED_BY varchar(50),
    UPDATE_TS datetime(3),
    UPDATED_BY varchar(50),
    DELETE_TS datetime(3),
    DELETED_BY varchar(50),
    A_VALUE integer,
    C_VALUE integer,
    --
    D_VALUE integer,
    --
    primary key (ID)
)^
-- end INHERIT_D

同样, 启动报错了, 继续研究也没有太大意义了
ERROR

结论: CUBA 的实体继承策略不可复合