3 继承映射
3.1 一个继承结构使用一个表(Table per class hierarchy)
这种方法在JPA中是InheritanceType.SINGLE_TABLE。
优点:简单,性能好,是多态操作性能最好的方式。
缺点:子类的字段必须定义成nullable,数据可能不是规范化的,存在数据一致性和易维护问题。
适用:简单继承结构,特别是子类属性比较少的情况。
例子:Billing是父类,CreditCard和BankAccount是两个子类。
@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="DISC", discriminatorType=DiscriminatorType.STRING)
@DiscriminatorValue("BILLING")

public abstract class Billing1 ...{
@Id private int id;
private String owner;
}

@Entity
@DiscriminatorValue("CREDITCARD")

public class CreditCard1 extends Billing1 ...{
private String number;
}

@Entity
@DiscriminatorValue("BANK")

public class BankAccount1 extends Billing1 ...{
private String account;
}

数据库表只有一个:
create table "BILLING1"(
"DISC" VARCHAR(31) not null,
"ID" INTEGER not null,
"OWNER" VARCHAR(255),
"ACCOUNT" VARCHAR(255),
"NUMBER" VARCHAR(255),
constraint "SYS_PK_1845" primary key ("ID")
);
create unique index "SYS_PK_1845" on "BILLING1"("ID");

































3.2 各子类使用单独的表(Table per subclass)
这种方法在JPA中是InheritanceType.JOINED。
优点:数据是规范化的,支持多态查询和多态关联。
缺点:对复杂的继承结构,该方法性能不好。
适用:需要多态查询和多态关联,特别是子类的属性较多的情况。
例子:
@Entity
@Inheritance(strategy=InheritanceType.JOINED)

public class Billing2 ...{
@Id private int id;
private String owner;
}

@Entity

public class CreditCard2 extends Billing2 ...{
private String number;
}

@Entity

public class BankAccount2 extends Billing2 ...{
private String account;
}

数据库表是:
create table "BILLING2"(
"ID" INTEGER not null,
"OWNER" VARCHAR(255),
constraint "SYS_PK_1846" primary key ("ID")
);
create unique index "SYS_PK_1846" on "BILLING2"("ID");

create table "CREDITCARD2"(
"ID" INTEGER not null,
"NUMBER" VARCHAR(255),
constraint "SYS_PK_1874" primary key ("ID")
);
alter table "CREDITCARD2"
add constraint "FK4FC2E7898F29E03D"
foreign key ("ID")
references "BILLING2"("ID");
create unique index "SYS_PK_1874" on "CREDITCARD2"("ID");
create index "SYS_IDX_1944" on "CREDITCARD2"("ID");

create table "BANKACCOUNT2"(
"ID" INTEGER not null,
"ACCOUNT" VARCHAR(255),
constraint "SYS_PK_1842" primary key ("ID")
);
alter table "BANKACCOUNT2"
add constraint "FKDB157E218F29E03D"
foreign key ("ID")
references "BILLING2"("ID");
create unique index "SYS_PK_1842" on "BANKACCOUNT2"("ID");
create index "SYS_IDX_1904" on "BANKACCOUNT2"("ID");




















































3.3 支持多态的各具体实体类使用单独的表(Table per concrete class with implicit polymorphism)。
优点:比较简单。
缺点:对多态关联的支持不好,多态查询也有问题(一个多态查询需要对应多条查询语句)。
适用:复杂继承结构中的顶层结构(一般不需要多态操作),并且基类修改的可能性不大的情况。特别适用于不采用JPA接口(如JDBC)的查询。
例子:
@MappedSuperclass

public class Billing3 ...{
private String owner;
}

@Entity

public class CreditCard3 extends Billing3 ...{
@Id private int id;
private String number;
}

@Entity

public class BankAccount3 extends Billing3 ...{
@Id private int id;
private String account;
}

数据库表是:
create table "CREDITCARD3"(
"ID" INTEGER not null,
"OWNER" VARCHAR(255),
"NUMBER" VARCHAR(255),
constraint "SYS_PK_1875" primary key ("ID")
);
create unique index "SYS_PK_1875" on "CREDITCARD3"("ID");

create table "BANKACCOUNT3"(
"ID" INTEGER not null,
"OWNER" VARCHAR(255),
"ACCOUNT" VARCHAR(255),
constraint "SYS_PK_1843" primary key ("ID")
);
create unique index "SYS_PK_1843" on "BANKACCOUNT3"("ID");



































3.4 采用Union的各具体实体类使用单独的表(Table per concrete class with unions)
这种方式在JPA中是InheritanceType.TABLE_PER_CLASS。
优点:支持多态查询和多态关联。
缺点:TABLE_PER_CLASS在JPA中是可选的,也就是说不能保证每个EJB 3.0的容器都支持这种方式。
适用:如果需要考虑可移植性问题,不推荐使用本方法。
例子:
@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)

public class Billing4 ...{
@Id private int id;
private String owner;
}

@Entity

public class CreditCard4 extends Billing4 ...{
private String number;
}

@Entity

public class BankAccount4 extends Billing4 ...{
private String account;
}

数据库表是:
create table "BILLING4"(
"ID" INTEGER not null,
"OWNER" VARCHAR(255),
constraint "SYS_PK_1847" primary key ("ID")
);
create unique index "SYS_PK_1847" on "BILLING4"("ID");

create table "CREDITCARD4"(
"ID" INTEGER not null,
"OWNER" VARCHAR(255),
"NUMBER" VARCHAR(255),
constraint "SYS_PK_1876" primary key ("ID")
);
create unique index "SYS_PK_1876" on "CREDITCARD4"("ID");

create table "BANKACCOUNT4"(
"ID" INTEGER not null,
"OWNER" VARCHAR(255),
"ACCOUNT" VARCHAR(255),
constraint "SYS_PK_1844" primary key ("ID")
);
create unique index "SYS_PK_1844" on "BANKACCOUNT4"("ID");










































由于Billing类不是抽象类,所以数据库中有Billing4表;可以将Billing设计为abstract,则不会出现Billing4表。
任何一种映射方法可以从抽象类继承,也可以从实体类继承;但是JPA规范不允许从接口继承(Hibernate支持从接口继承)。另外,还可以混用继承方法,例如采用一个继承结构使用一个表,但是某个表采用各子类使用单独的表方法。最后,在选用不同的继承映射方法前,请考虑是否可以采用设计模式将继承转化为合成,使业务模型更趋简单。
本文的最后一部分将描述实体和实体的关联关系。