您的位置:首页 > 其它

Hibernate深入学习(三):继承与多态查询,joined-subclass与union-subclass

2016-06-22 18:02 337 查看
在上一篇中,我们对hibernate中3种继承有了初步了解,并对subclass进行了测试,以及知道了它的诸多缺点,这些缺点导致subclass在开发中并不常用,接下来我们看看剩下的两种继承方式:joined-subclass与union-subclass

本文中使用的实体类与测试代码同前篇,不再赘述

首先我们看看joined-class的实体映射文件:主要看元素

<?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="cn.sina.join.subclass" auto-import="false">
<class name="Person" table="joined_person">
<id name="id" column="pid" length="10" type="java.lang.Integer">
<generator class="increment"></generator>
</id>
<property name="name" type="java.lang.String" length="32" not-null="true"></property>
<property name="age" type="java.lang.Integer" length="5" not-null="true"></property>

<joined-subclass name="Worker" table="joined_worker">
<key column="person_id"></key>
<property name="job" type="java.lang.String" length="32"></property>
<property name="unit" type="java.lang.String" length="32"></property>
</joined-subclass>
</class>
</hibernate-mapping>


我们已经知道joined-subclass是会产生两张表的,中的table用于指定子类表名,并且使用person_id来与父类表建立关联

测试代码见前篇,插入的测试结果如下:

Hibernate:
select
max(pid)
from
joined_person
Hibernate:
insert
into
joined_person
(name, age, pid)
values
(?, ?, ?)
Hibernate:
insert
into
joined_person
(name, age, pid)
values
(?, ?, ?)
Hibernate:
insert
into
joined_worker
(job, unit, person_id)
values
(?, ?, ?)


可以看到发出了4条sql语句,除了第一句省略,其它共3条insert语句

因为joined-subclass采用的是父类表存储父类字段,子类表存储子类字段,用外键关联,

因此第一条insert语句对应的是session.save(person);

第二天insert语句是在 session.save(worker)时,将worker继承自父类的字段插入,

最后一条insert语句是插入将worker插入到子类表中,它直插入子类独有的字段

在做查询时,请使用类全名的形式,例如:

session.createQuery("from cn.sina.join.subclass.Person").list();


查询的结果如下:

Hibernate:
select
person0_.pid as pid1_,
person0_.name as name1_,
person0_.age as age1_,
person0_1_.job as job2_,
person0_1_.unit as unit2_,
case
when person0_1_.person_id is not null then 1
when person0_.pid is not null then 0
end as clazz_
from
joined_person person0_
left outer join
joined_worker person0_1_
on person0_.pid=person0_1_.person_id
Hibernate:
select
worker0_.person_id as pid1_,
worker0_1_.name as name1_,
worker0_1_.age as age1_,
worker0_.job as job2_,
worker0_.unit as unit2_
from
joined_worker worker0_
inner join
joined_person worker0_1_
on worker0_.person_id=worker0_1_.pid
[Person [id=1, name=tom, age=10], Worker [job=washer, unit=bj], Person [id=3, name=tom, age=10], Worker [job=washer, unit=bj]]
[Worker [job=washer, unit=bj], Worker [job=washer, unit=bj]]


可以看出查询父类使用的是一个左外连接查询,同时查询出了子类,而查询子类使用的是一个内连接查询

最后一个是union-subclass,它和joined-subclass类似,它将父类对应一张表,子类对应一张表,此时的子类表包括了从父类中继承的字段,它的实体映射文件如下:注意看

<?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="cn.sina.union.subclass" auto-import="false">
<class name="Person" table="union_person">
<id name="id" column="pid" length="10" type="java.lang.Integer">
<generator class="increment"></generator>
</id>
<property name="name" type="java.lang.String" length="32" not-null="true"></property>
<property name="age" type="java.lang.Integer" length="5" not-null="true"></property>

<union-subclass name="Worker" table="union_worker">
<property name="job" type="java.lang.String" length="32"></property>
<property name="unit" type="java.lang.String" length="32"></property>
</union-subclass>
</class>
</hibernate-mapping>


可以看出union-subclass只需要指定一个表名即可

插入测试结果很简单,就是发出两条inert语句,插入到对应的表中即可

Hibernate:
select
max(ids_.pid)
from
( select
pid
from
union_person
union
select
pid
from
union_worker
) ids_
Hibernate:
insert
into
union_person
(name, age, pid)
values
(?, ?, ?)
Hibernate:
insert
into
union_worker
(name, age, job, unit, pid)
values
(?, ?, ?, ?, ?)


查询结果如下(hql也要使用类全名)

Hibernate:
select
person0_.pid as pid3_,
person0_.name as name3_,
person0_.age as age3_,
person0_.job as job4_,
person0_.unit as unit4_,
person0_.clazz_ as clazz_
from
( select
pid,
name,
age,
null as job,
null as unit,
0 as clazz_
from
union_person
union
select
pid,
name,
age,
job,
unit,
1 as clazz_
from
union_worker
) person0_
Hibernate:
select
worker0_.pid as pid3_,
worker0_.name as name3_,
worker0_.age as age3_,
worker0_.job as job4_,
worker0_.unit as unit4_
from
union_worker worker0_
[Person [id=1, name=tom, age=10], Worker [job=washer, unit=bj]]
[Worker [job=washer, unit=bj]]


我们着重看一下父类的查询sql,比较有意思,它也将子类查询出来了,它先通过union将两张表联合查询,再从联合查询的结果中获取结果。

最后分析下二者的缺点:

1.插入与查询的效率都低下

2.union-subclass在更新父类表时效率低下
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  hibernate 继承