08-07
08

继承- Table per subclass

上一个主题 ,在使用Table per class hierarchy映射继承关系时,会有大量的栏位有NULL的情况,好处是使用一个表格,查询时只需一次SQL。

Table per subclass的继承映射方式,给予父类与子类分别的表格,而父类与子类对应的表格透过外键来产生关联,具体的说,User类别、 DefaultUser类别与PowerUser类别所映射的表格如下:
Table per subclass

其中user表格的id与defaultuser及poweruser的id 一致,具体的说,在储存DefaultUser实例时,id与name属性记录在user表格中,而someProperty记录在 defaultuser中,假设user表格的id值为1,则defaultuser表格对应的该笔记录其id值也会为一。

可以使用以下的SQL建立资料表:
create table T_Defaultuser (
    id bigint not null,
    someProperty varchar(255),
    primary key (id)
)

create table T_Poweruser (
    id bigint not null,
    otherProperty varchar(255),
    primary key (id)
)

create table T_USER (
    id bigint not null auto_increment,
    name varchar(255),
    primary key (id)
)

alter table T_Defaultuser
    add index id (id),
    add constraint id
    foreign key (id)
    references T_USER (id)

alter table T_Poweruser
    add index id (id),
    add constraint id
    foreign key (id)
    references T_USER (id)

在映射文件上,如下定义:

  • 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>

<property name="name" column="name"/>

<joined-subclass name="DefaultUser"
table="T_Defaultuser">
<key column="id" foreign-key="id"/>
<property name="someProperty" column="someProperty" />
</joined-subclass>

<joined-subclass name="PowerUser"
table="T_Poweruser">
<key column="id" foreign-key="id"/>
<property name="otherProperty" column="otherProperty" />
</joined-subclass>
</class>

</hibernate-mapping>

<joined-subclass>指明了子类别与所对应的表格,<key column>指明子类别的对应表格中,哪一个栏位要与父类别的主键一致,来看Hibernate储存时的例子:
Hibernate:
    insert
    into
        T_USER
        (name)
    values
        (?)
Hibernate:
    insert
    into
        T_Poweruser
        (otherProperty, id)
    values
        (?, ?)
Hibernate:
    insert
    into
        T_USER
        (name)
    values
        (?)
Hibernate:
    insert
    into
        T_Defaultuser
        (someProperty, id)
    values
        (?, ?)

来看Hibernate查询时的例子:
Hibernate:
    select
        user0_.id as id0_,
        user0_.name as name0_,
        user0_1_.someProperty as someProp2_1_,
        user0_2_.otherProperty as otherPro2_2_,
        case
            when user0_1_.id is not null then 1
            when user0_2_.id is not null then 2
            when user0_.id is not null then 0
        end as clazz_
    from
        T_USER user0_
    left outer join
        T_Defaultuser user0_1_
            on user0_.id=user0_1_.id
    left outer join
        T_Poweruser user0_2_
            on user0_.id=user0_2_.id

使用 继承 - Table per concrete class 中的储存程式片段,则查询表格时可以发现以下的结果:

mysql> select * from user;
+-----+-------------+
| id  | name        |
+-----+-------------+
|  1  | caterpillar |
|  2  | Bush        |
+-----+-------------+
2 rows in set (0.00 sec)

mysql> select * from defaultuser;
+----+------------------+
| id | someProperty     |
+----+------------------+
|  2 | hu....hu...      |
+----+------------------+
1 row in set (0.00 sec)

mysql> select * from poweruser;
+----+-------------------+
| id | otherProperty     |
+----+-------------------+
|  1 | Bla...Bla...      |
+----+-------------------+
1 row in set (0.00 sec)


仔细观察一下,看看defaultuser与poweruser表格中的id各自是对应于user表格中的哪笔资料。

效能是这个映射类型需要考量的,在复杂的类别继承下,新增资料必须对多个表格进行,而查询时,跨越多个表格的join也可能引发效能上的问题。

如果您需要多型查询,而子类别相对来说有较多新增的属性,则可以使用这种映射方式。


文章来自: 本站原创
引用通告: 查看所有引用 | 我要引用此文章
Tags: 继承 subclass
相关日志:
评论: 0 | 引用: 0 | 查看次数: 689
发表评论
昵 称:
密 码: 游客发言不需要密码.
内 容:
验证码: 验证码
选 项:
虽然发表评论不用注册,但是为了保护您的发言权,建议您注册帐号.
字数限制 1000 字 | UBB代码 开启 | [img]标签 关闭