Hibernate(七):继承映射

来源:互联网 发布:有个微信精准定位软件 编辑:程序博客网 时间:2024/05/22 17:38

  继承是面向对象的特性,在Hibernate 中是以面向对象的思想进行持久化操作,所以在Hibernate中数据表所映射的实体对象也是可以存在继承关系的。主要有三种继承关系:

1.类继承树映射成一张表(subclass)

     将域模型中的每一个实体对象映射到一个独立的表中,也就是说不用在关系数据模型中考虑域模型中的继承和多态。

(1)使用subclass的继承映射可以实现继关系中父类和子类使用一张表。

(2)因为父类和子类的实例都保存在一张表中,需要在这个表中增加一列,使用该类来区分每行记录到底是哪个类的实例,这个列被称为辨别者列(discriminator)

  •  在这种映射策略下,使用subclass来映射子类。使用class或subclass的discriminator-value属性指定辨别者列的值

 (3)所有的子类定义的字段都不能有非空约束。如果为那些字段添加非空约束,那么父类的实例在那些列中并没有值,这将引起数据库完整性冲突,导致数据添加失败。

实例:学生对象(Student)和 职员对象(Staff)共同继承了人的实体对象(Persont)。将这三个类映射到一张表中,为了辨明两个子类,需要在表中添加一个字段(辨别者列)type ,用来区分存储不同实体对象信息


代码:

Person.java

public class Person {private Integer id;// 唯一性标识private String name;// 姓名private String sex;// 性别private Integer age;// 年龄public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getSex() {return sex;}public void setSex(String sex) {this.sex = sex;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}}
Student.java
public class Student extends Person {private String school;//所在学校public String getSchool() {return school;}public void setSchool(String school) {this.school = school;}}
Staff.java

public class Staffer extends Person {private String company;//所在的公司名称public String getCompany() {return company;}public void setCompany(String company) {this.company = company;}}

映射文件:

<?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="com.mr.person"> <class name="Person" table="tab_person"> <id name="id"><generator class="native"/></id><!-- 声明一个鉴别器 --><discriminator column="type" type="string"/> <!-- 映射自有属性 --><property name="name" not-null="true"/><property name="age" type="int"/> <property name="sex" type="string"/> <!-- 声明子类Student --><subclass name="Student" discriminator-value="学生"><property name="school"/></subclass> <!-- 声明子类Staffer --><subclass name="Staffer" discriminator-value="职员"><property name="company"/></subclass> </class> </hibernate-mapping>

向表中插入数据,结果如下(两个子类信息在一张表中):


2.每个子类映射成一张表(joined-class)

 (1)  采用 joined-subclass 元素的继承映射可以实现每个子类一张表

  •  采用这种映射策略时,父类实例保存在父类表中,子类实例由父类表和子类表共同存储。因为子类实例也是一个特殊的父类实例,因此必然也包含了父类实例的属性。于是将子类和父类共有的属性保存在父类表中,子类增加的属性,则保存在子类表中。
  •  在这种映射策略下,无须使用鉴别者列,但需要为每个子类使用 key 元素映射共有主键。
 (2)子类增加的属性可以添加非空约束。因为子类的属性和父类的属性没有保存在同一个表中
    实例:将继承Person的两个子类映射到一张表中


代码:

<?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="com.mr.person"> <class name="Person" table="tab_person1"> <id name="id"><generator class="native"/></id> <!-- 映射自有属性 --><property name="name" not-null="true"/><property name="age" type="int"/> <property name="sex" type="string"/> <!-- 映射子类Student --><joined-subclass name="Student" table="tab_student"><key column="id"/><property name="school"/></joined-subclass><!-- 映射子类Staffer --><joined-subclass name="Staffer" table="tab_staffer"><key column="id" /><property name="company"/></joined-subclass> </class> </hibernate-mapping>

插入数据,结果如下:


3.每个具体类映射成一张表(union-class)

     将域模型中的每个类映射到一张表中,通过关系数据模型中的外键来描述表之间的继承关系。相当于按照域模型的结构来建立数据库中的表,并通过外键来建立表之间的继承关系。

(1)采用 union-subclass 元素可以实现将每一个实体对象映射到一个独立的表中。

  • 子类增加的属性可以有非空约束 --- 即父类实例的数据保存在父表中,而子类实例的数据保存在子类表中。
  • 子类实例的数据仅保存在子类表中, 而在父类表中没有任何记录
  • 在这种映射策略下,子类表的字段会比父类表的映射字段要多,因为子类表的字段等于父类表的字段、加子类增加属性的总和
  • 在这种映射策略下,既不需要使用鉴别者列,也无须使用 key 元素来映射共有主键.   
  • 使用 union-subclass 映射策略是不可使用 identity 的主键生成策略, 因为同一类继承层次中所有实体类都需要使用同一个主键种子, 即多个持久化实体对应的记录的主键应该是连续的. 受此影响, 也不该使用 native 主键生成策略, 因为 native 会根据数据库来选择使用 identity 或 sequence.
实例:将每个具体类Student和Staff映射成一张表


代码:

<?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="com.mr.person"> <class name="Person" abstract="true"> <id name="id"><!-- 主键生成策略为手动分配 --><generator class="assigned"/></id> <!-- 映射自有属性 --><property name="name" not-null="true"/><property name="age" type="int"/> <property name="sex" type="string"/> <!-- 映射子类Student --><union-subclass name="Student" table="tab_student2"><property name="school"/></union-subclass><!-- 映射子类Staffer --><union-subclass name="Staffer" table="tab_staffer2"><property name="company"/></union-subclass> </class> </hibernate-mapping>
结果如下:


4.三种继承映射方式的比较



阅读全文
0 0
原创粉丝点击