public class Person {
private Integer id;
private String name;
private Integer age;
}
public class Worker extends Person{
private String job;
private String unit;
}
hibernate为我们提供了三种形式来表示继承关系,分别是:subclass,joined-subclass,union-subclass
1.subclass
父类和子类存在同一张表中,其中的role
字段是辨别者列,用于辨别这条记录是父类还是子类
2.join-subclass
不同于subclass,joined-subclass和union-subclass都是需要两种表来存储。
父类表存储父类字段,子类表存储子类字段,虽然没有了辨别者列,但是额外增加了一个person_id
来表示二者的关系\
3.union-subclass
这种方式只要和joined-subclass比较一下就很清楚了,join-subclass是父类表存储父类字段,子类表存储子类字段,那么union-subclass就是父类表存储父类字段,而子类表既要存储父类字段,也要存储子类字段
1.subclass
请注意class和subclass的discriminator-value
属性,由于父类表和子类表共存在一张表中,因此需要一个辨别者列,我们需要分别对父类和子类设置辨别者列的值,本例中使用PERSON和WORKER。
在中间位置的,它必须在id元素之后,property元素之前,否则会报错,它用于设置辨别者列字段名,column=”role”
<?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.subclass">
<class name="Person" table="ex_person" **discriminator-value="PERSON"**>
<id name="id" column="pid" length="10" type="java.lang.Integer">
<generator class="increment"></generator>
</id>
<!-- 辨别者列 -->
**<discriminator column="role" type="string"></discriminator>**
<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>
**<subclass name="Worker" discriminator-value="WORKER">**
<property name="job" type="java.lang.String" length="32"></property>
<property name="unit" type="java.lang.String" length="32"></property>
</subclass>
</class>
</hibernate-mapping>
Person person = new Person();
person.setAge(10);
person.setName("tom");
session.save(person);
Worker worker = new Worker();
worker.setAge(20);
worker.setName("jerry");
worker.setJob("washer");
worker.setUnit("bj");
session.save(worker);
发出的sql如下,除了第一个用于寻找主键最大值外,我们可以看到在插入的是同一张表,同时辨别者列的值已经确定下来了
Hibernate: select max(pid) from ex_person
Hibernate: insert into ex_person (name, age, role, pid) values (?, ?, 'PERSON', ?)
Hibernate: insert into ex_person (name, age, job, unit, role, pid) values (?, ?, ?, ?, 'WORKER', ?)
接下我们看看多态查询,代码如下:
““
//hql查询
List persons = session.createQuery(“from Person”).list();
List workers = session.createQuery(“from Worker”).list();
System.out.println(persons);
System.out.println(workers);
发出的sql以及结果如下:
````
Hibernate:
select
person0_.pid as pid0_,
person0_.name as name0_,
person0_.age as age0_,
person0_.job as job0_,
person0_.unit as unit0_,
person0_.role as role0_
from
ex_person person0_
Hibernate:
select
person0_.pid as pid0_,
person0_.name as name0_,
person0_.age as age0_,
person0_.job as job0_,
person0_.unit as unit0_,
person0_.role as role0_
from
ex_person person0_
where
worker0_.role='WORKER'
[Person [id=1, name=tom, age=10], Worker [job=washer, unit=bj]]
[Worker [job=washer, unit=bj]]
结果在查询父类时,会同时查询出子类,而在查询子类时,使用了where条件,通过辨别者列查询
subclass的缺点:
1.子类独有的字段无法设置not-null约束,即job和unit无法非空,毕竟父类中没有这两个字段
2.如果继承树过于庞大,不便于管理,本例只是两个实体,如果有n个实体之间继承,将会很麻烦