通常,選用了一種繼承的映射模式之後,就無法再套用另一種模式,但在某些情況下,您還是可以混用兩種繼承模式,例如混用 繼 承 - Table per class hierarchy 與 繼承 - Table per subclass,用Table per class hierarchy的方式將 DefaultUser 映射至T_USER表格,而用Table per subclass的方式將PowerUser的新定義的屬性映射至另一個T_Poweruser表格。
create table T_PowerUser (
id bigint not null,
otherProperty varchar(255),
primary key (id)
)
create table T_USER (
id bigint not null auto_increment,
userType varchar(255) not null,
name varchar(255),
someProperty varchar(255),
primary key (id)
)
alter table T_PowerUser
add index id (id),
add constraint id
foreign key (id)
references T_USER (id)
您可以使用<join>標籤來加以定義,例如:
- User.hbm.xml
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping
PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="onlyfun.caterpillar">
<class name="User" table="T_USER">
<id name="id" column="id">
<generator class="native"/>
</id>
<discriminator column="userType"/>
<property name="name" column="name"/>
<subclass name="DefaultUser"
discriminator-value="Default">
<property name="someProperty" column="someProperty" />
</subclass>
<subclass name="PowerUser"
discriminator-value="Power">
<join table="T_PowerUser">
<key column="id" foreign-key="id"/>
<property name="otherProperty" column="otherProperty"/>
</join>
</subclass>
</class>
</hibernate-mapping>
儲存物件時的一個例子如下:
Hibernate:
insert
into
T_USER
(name, userType)
values
(?, 'Power')
Hibernate:
insert
into
T_PowerUser
(otherProperty, id)
values
(?, ?)
Hibernate:
insert
into
T_USER
(name, someProperty, userType)
values
(?, ?, 'Default')
insert
into
T_USER
(name, userType)
values
(?, 'Power')
Hibernate:
insert
into
T_PowerUser
(otherProperty, id)
values
(?, ?)
Hibernate:
insert
into
T_USER
(name, someProperty, userType)
values
(?, ?, 'Default')
查詢時的一個例子如下:
Hibernate:
select
user0_.id as id0_,
user0_.name as name0_,
user0_.someProperty as someProp4_0_,
user0_1_.otherProperty as otherPro2_1_,
user0_.userType as userType0_
from
T_USER user0_
left outer join
T_PowerUser user0_1_
on user0_.id=user0_1_.id
select
user0_.id as id0_,
user0_.name as name0_,
user0_.someProperty as someProp4_0_,
user0_1_.otherProperty as otherPro2_1_,
user0_.userType as userType0_
from
T_USER user0_
left outer join
T_PowerUser user0_1_
on user0_.id=user0_1_.id
儲存的表格範例如下:
mysql> select * from t_user;
+----+----------+-------------+--------------+
| id | userType | name | someProperty |
+----+----------+-------------+--------------+
| 1 | Power | caterpillar | NULL |
| 2 | Default | Bush | hu....hu... |
+----+----------+-------------+--------------+
2 rows in set (0.00 sec)
mysql> select * from t_poweruser;
+----+---------------+
| id | otherProperty |
+----+---------------+
| 1 | Bla...Bla... |
+----+---------------+
1 row in set (0.00 sec)
+----+----------+-------------+--------------+
| id | userType | name | someProperty |
+----+----------+-------------+--------------+
| 1 | Power | caterpillar | NULL |
| 2 | Default | Bush | hu....hu... |
+----+----------+-------------+--------------+
2 rows in set (0.00 sec)
mysql> select * from t_poweruser;
+----+---------------+
| id | otherProperty |
+----+---------------+
| 1 | Bla...Bla... |
+----+---------------+
1 row in set (0.00 sec)
這個混用模式的問題是,在繼承的廣度大時,outer join會成為問題,您可以在<join>上加上fetch屬性為select:
...
<join table="T_PowerUser" fetch="select">
<key column="id" foreign-key="FK_USER"/>
<property name="otherProperty" column="otherProperty"/>
</join>
...
則查詢時的一個例子如下,原來的一次查詢換成了兩次select查詢:
Hibernate:
select
user0_.id as id0_,
user0_.name as name0_,
user0_.someProperty as someProp4_0_,
user0_.userType as userType0_
from
T_USER user0_
Hibernate:
select
user_1_.otherProperty as otherPro2_1_
from
T_PowerUser user_1_
where
user_1_.id=?
select
user0_.id as id0_,
user0_.name as name0_,
user0_.someProperty as someProp4_0_,
user0_.userType as userType0_
from
T_USER user0_
Hibernate:
select
user_1_.otherProperty as otherPro2_1_
from
T_PowerUser user_1_
where
user_1_.id=?