繼承映射策略之----每個(gè)子類(lèi)一張表
在每個(gè)子類(lèi)一張表的映射策略中,每一個(gè)子類(lèi)都有一張屬于自己的表,但是這張表只包括了定義在這個(gè)子類(lèi)上面的屬性而已,定義在它的父類(lèi)的屬性它的表里面是沒(méi)有的,所以這樣的方式映射的話,就不會(huì)浪費(fèi)一點(diǎn)資源了,每一張表,每一列都是不可少的,也不會(huì)出現(xiàn)冗余。這種格式是有點(diǎn)像TABLE_PER_CLASS的策略,只不過(guò)這種方案是規(guī)范的,沒(méi)有像TABLE_PER_CLASS一樣重復(fù)定義列,在這里我們叫它JOINED策略。
按我們的例子,這種策略映射出來(lái)的話,數(shù)據(jù)庫(kù)的結(jié)構(gòu)將如下所示:
create table Person (
id integer primary key not null,
firstName varchar(255),
lastName varchar(255),
);
create table Customer (
id integer primary key not null,
street varchar(255),
city varchar(255),
state varchar(255),
zip varchar(255),
);
create table Employee (
EMP_PK integer primary key not null,
employeeId integer
);
當(dāng)持久化管理器加載一個(gè)類(lèi)或者查詢一個(gè)子類(lèi)的時(shí)候,它必須要對(duì)數(shù)據(jù)庫(kù)做連接動(dòng)作,所以我們必須要保存這幾張表有一個(gè)能夠彼此連接起來(lái)的列。在我們的例子里面,EMPLOYEE, CUSTOMER, 和 PERSON表共享同樣的主鍵值,這種策略的注釋也是挺簡(jiǎn)單的:
@Entity
@Inheritance(strategy=InheritanceType.JOINED)
public class Person {

}
@Entity
public class Customer extends Person {

}
@Entity
@PrimaryKeyJoinColumn
(name="EMP_PK")
public class Employee extends Customer {

}
在持久化的時(shí)候,持久化管理器需要知道每一張表用哪一列來(lái)進(jìn)行連接,所以當(dāng)我們要指定某一列的時(shí)候,就可以用如下注釋?zhuān)?/p>
@javax.persistence.PrimaryKeyJoinColumn,它的聲明如下:
package javax.persistence;
@Target({TYPE, METHOD, FIELD})
public @interface PrimaryKeyJoinColumn
String name( ) default "";
String referencedColumnName( ) default "";
String columnDefinition( ) default "";
}
name()方法提出你此表中需要用來(lái)連接的列的名字,它默認(rèn)是與父類(lèi)的主鍵進(jìn)行連接,當(dāng)我們不想與父類(lèi)的主鍵進(jìn)行連接時(shí),我們可以用referencedColumnName( )這個(gè)方法來(lái)指定你要連接父類(lèi)的哪個(gè)具體的列,它可以被定義為父類(lèi)的任意列,但是默認(rèn)是連接父類(lèi)的主鍵列,如果從父類(lèi)到子類(lèi)的主鍵名都是一樣的,那么這個(gè)屬性就沒(méi)必要再設(shè)了,因?yàn)镃ustomer和Person的主鍵是一樣的,所以在Customer里面不需要定義任何額外的屬性,一切默認(rèn)就可以了,但是由于Employee里面的主鍵名和其它的不一樣,所以它必須顯式地聲明它的主鍵是哪一個(gè)。如果有的類(lèi)有復(fù)合主鍵,那么可以用這個(gè)注釋?zhuān)?br />
@javax.persistence.PrimaryKeyJoinColumns
package javax.persistence;
@Target({TYPE, METHOD, FIELD})
public @interface PrimaryKeyJoinColumns {
@PrimaryKeyJoinColumn[] value( );
}
它包括了多個(gè)@PrimaryKeyJoinColumn的注釋。
注意:有些持久化實(shí)現(xiàn)這種策略會(huì)需要一個(gè)辨別器列,雖然大部份是不需要的,所以最好是在使用前查看一下你的持久化提供商的實(shí)現(xiàn)說(shuō)明。
優(yōu)點(diǎn):
這種策略雖然沒(méi)有SINGLE_TABLE策略的速度快,但是你可以定義任何的非空約束在任何的表里面,并且這種模式是規(guī)范化的。
缺點(diǎn):
唯一的缺點(diǎn)就是沒(méi)有SINGLE_TABLE 策略的性能好。
到現(xiàn)在我們?nèi)N處理繼承映射的策略都說(shuō)完了,在不同的場(chǎng)合和環(huán)境下選擇不同的映射策略是最明智的選擇,沒(méi)有一種策略可以勝任所有場(chǎng)合,否則的話,出一種就可以了,干嘛還出三種呢。希望大家在實(shí)際工作中選出適合自己的映射策略,更好的提高工作效率。