繼承 - 混合模式


通常,選用了一種繼承的映射模式之後,就無法再套用另一種模式,但在某些情況下,您還是可以混用兩種繼承模式,例如混用 繼 承 - 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')

查詢時的一個例子如下:
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

儲存的表格範例如下:
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)

這個混用模式的問題是,在繼承的廣度大時,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=?