08-07
08
继承- Table per subclass
作者:Java伴侣 日期:2008-07-08
续 上一个主题 ,在使用Table per class hierarchy映射继承关系时,会有大量的栏位有NULL的情况,好处是使用一个表格,查询时只需一次SQL。
Table per subclass的继承映射方式,给予父类与子类分别的表格,而父类与子类对应的表格透过外键来产生关联,具体的说,User类别、 DefaultUser类别与PowerUser类别所映射的表格如下:
其中user表格的id与defaultuser及poweruser的id 一致,具体的说,在储存DefaultUser实例时,id与name属性记录在user表格中,而someProperty记录在 defaultuser中,假设user表格的id值为1,则defaultuser表格对应的该笔记录其id值也会为一。
可以使用以下的SQL建立资料表:
在映射文件上,如下定义:
<joined-subclass>指明了子类别与所对应的表格,<key column>指明子类别的对应表格中,哪一个栏位要与父类别的主键一致,来看Hibernate储存时的例子:
来看Hibernate查询时的例子:
使用 继承 - Table per concrete class 中的储存程式片段,则查询表格时可以发现以下的结果:
仔细观察一下,看看defaultuser与poweruser表格中的id各自是对应于user表格中的哪笔资料。
效能是这个映射类型需要考量的,在复杂的类别继承下,新增资料必须对多个表格进行,而查询时,跨越多个表格的join也可能引发效能上的问题。
如果您需要多型查询,而子类别相对来说有较多新增的属性,则可以使用这种映射方式。
Table per subclass的继承映射方式,给予父类与子类分别的表格,而父类与子类对应的表格透过外键来产生关联,具体的说,User类别、 DefaultUser类别与PowerUser类别所映射的表格如下:
其中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)
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
(?, ?)
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
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也可能引发效能上的问题。
如果您需要多型查询,而子类别相对来说有较多新增的属性,则可以使用这种映射方式。
评论: 0 | 引用: 0 | 查看次数: 687
发表评论