hibernate---继承映射
union-subclass:是将子类映射到不同的表中,当以父类查询子类所对应的数据时,这时hibernate将使用表子查询语句语句查询数据(即将查询先用联合查询查询所有的子类对应的表中的数据,将联合查询到的数据作为数据源进行查询)
在hibernate中继承映射一共有三种,如下:
- 基于类上层次的继承关系
- 基于类上层次和表上层次的继承关系
- 基于类上层次的继承关系(识别器)
前两种继承映射都有各自明显的缺点,第一种基于类上层次的继承关系,解决了类上的雍和,但没有解决表中结构重复,而第二种则在数据查询上会产生笛卡尔积,这将大大降低数据库查询的性能!!!
下面重点讲解第一种基于类上层次的继承关系
准备数据表:
create table test1(
id int(11) not null auto_increment,
test1 varchar(255),
primary key(id)
);
create table test2(
id int(11) not null auto_increment,
test2 varchar(255),
primary key(id)
);
准备pojo类
package it.hibernate.factory;
import java.io.Serializable;
public class Test1 extends Test implements Serializable{
private String test1;
public String getTest1() {
return test1;
}
public void setTest1(String test1) {
this.test1 = test1;
}
}
package it.hibernate.factory;
import java.io.Serializable;
public class Test2 extends Test implements Serializable{
private String test2;
public String getTest2() {
return test2;
}
public void setTest2(String test2) {
this.test2 = test2;
}
}
准备公共父类:
package it.hibernate.factory;
import java.io.Serializable;
public class Test implements Serializable {
private Integer id;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
}
配置配置文件Test.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>
<class name="it.hibernate.factory.Test" catalog="hibernate">
<id name="id" column="id" type="int">
<generator class="assigned"></generator>
</id>
<union-subclass table="test1" catalog="hibernate" name="it.hibernate.factory.Test1">
<property name="test1" column="test1"/>
</union-subclass>
<union-subclass table="test2" catalog="hibernate" name="it.hibernate.factory.Test2">
<property name="test2" column="test2"/>
</union-subclass>
</class>
</hibernate-mapping>
而Hibernate底层运用的技术是mysql中的union查询~~
union查询
作用:将具有想用字段数的表中查询的记录无条件拼接在一起
具体语法:
select 语句 union [union选项] select 语句 ...
观察下列:
准备四张表:
test1:
test2:
test3:
user:
不重复查询test1和test2和user中所有的记录
查询所有test1和test2和user中所有的记录
查询所有test1和test2和user中userName等于zl所有的记录
总结:union查询本质上是将表中具有相同字段数的表中的查询到的记录无条件拼接在一起,显示的字段一第一条查询的语句为主,当表中字段数不相同时则无法使用该查询语法!!
子表数据:
test1
test2
根据父类查询子类对象数据:
package it.hibernate.factory;
import org.hibernate.Query;
import org.hibernate.Session;
public class TestClass {
public static void main(String[] args) {
Session session = HibernateSessionFactory.getSession();
Test test = (Test)session.get(Test.class, 2);
System.out.println(test);
session.beginTransaction().commit();
}
}
控制台打印的sql语句结果为:
Hibernate:
select
test0_.id as id2_0_,
test0_.test1 as test1_3_0_,
test0_.test2 as test1_4_0_,
test0_.clazz_ as clazz_0_
from
( select
id,
null as test1,
null as test2,
0 as clazz_
from
hibernate.Test
union
select
id,
test1,
null as test2,
1 as clazz_
from
hibernate.test1
union
select
id,
null as test1,
test2,
2 as clazz_
from
hibernate.test2
) test0_
where
test0_.id=?
并抛出异常:
异常信息为test表不存在!!!!
解析:从上面的查询语句可以看出这是hibernate将在test和test1和test2表先联合查询将查询的结果作为数据源进行查询~~,而之所以会抛出异常信息是因为在配置test.hbm.xml文件时,我们并没有显示的指示test类要映射的表名,而hibernate在默认情况下会以类名作为表名进行映射(注意:hibernate不可以显示的指示两个类要映射相同的数据表,但可以一个隐式的指明要映射的表,一个显示的指定要映射的表),解决方法在test.hbm.xml文件中声明该类为抽象类:abstract="true"当声明为抽象类时,则hibernate在进行查询时会首先查询在配置中是否存在union-subclass继承形式的子类如果存在,则将以子类作为数据进行查询,如果不存在该union-subclass形式的子类,则讲以自己本身对应的数据表作为数据源进行查询操作
修改test.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>
<class name="it.hibernate.factory.Test" abstract="true" catalog="hibernate">
<id name="id" column="id" type="int">
<generator class="assigned"></generator>
</id>
<union-subclass table="test1" catalog="hibernate" name="it.hibernate.factory.Test1">
<property name="test1" column="test1"/>
</union-subclass>
<union-subclass table="test2" catalog="hibernate" name="it.hibernate.factory.Test2">
<property name="test2" column="test2"/>
</union-subclass>
</class>
</hibernate-mapping>
控制台打印结果为:
Hibernate:
select
test0_.id as id2_0_,
test0_.test1 as test1_3_0_,
test0_.test2 as test1_4_0_,
test0_.clazz_ as clazz_0_
from
( select
id,
test1,
null as test2,
1 as clazz_
from
hibernate.test1
union
select
id,
null as test1,
test2,
2 as clazz_
from
hibernate.test2
) test0_
where
test0_.id=?
Test [id=2]Test1 [test1=admin-root1]
可以看到这时已经成功查询到了数据!
总结:该继承模式是基于SQL中联合查询的继承,该继承模式在查询时会将父类及其所有子类的数据作为数据源进行表子查询,这就要求在该继承模式所有的子类对应的表时同一性质的表,具有同一字段数的数据表,该继承模式作用主要是对多个表中数据进行联合查询...
主要应用场景:当一张表的数据过大时,这时如果进行查询操作效率将很慢,解决方案是:将一张表进行拆分为多张数据表,并且每张表的结构完全相同,每张表存储特定规律的数据;但这有产生一个问题就是我们该对那张表进行查询呢?这时就可以运用该继承模式,设置一个公共的父类,将所有的子类对应的pojo对象继承与该父类,在进行查询时就会联合查询所有拆分表中的数据!!