在问题域中实体之间的继承关系在数据库中有多种体现方式。在hibernate中,要实现面向对象的对实体进行持久化操作,那么就需要对实体类进行继承关系映射。
根据数据表的不同形态,映射方案有三种
实体继承关系模型:
1.Tpc每个具体类一张表
mysql> show tables;
+-------------------+
| Tables_in_db_test |
+-------------------+
| tb_student |
| tb_worker |
+-------------------+
2 rows in set (0.00 sec)
表结构:
mysql> desc tb_student;
+--------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+--------------+------+-----+---------+-------+
| id | int(11) | NO | PRI | NULL | |
| name | varchar(255) | YES | | NULL | |
| sex | varchar(255) | YES | | NULL | |
| age | int(11) | YES | | NULL | |
| sno | varchar(255) | YES | | NULL | |
| school | varchar(255) | YES | | NULL | |
+--------+--------------+------+-----+---------+-------+
mysql> desc tb_worker;
+--------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+--------------+------+-----+---------+-------+
| id | int(11) | NO | PRI | NULL | |
| name | varchar(255) | YES | | NULL | |
| sex | varchar(255) | YES | | NULL | |
| age | int(11) | YES | | NULL | |
| no | varchar(255) | YES | | NULL | |
| salary | double | YES | | NULL | |
+--------+--------------+------+-----+---------+-------+
Person.hbm.xml
- <?xml version="1.0"?>
- <!DOCTYPE hibernate-mapping PUBLIC
- "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
- "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
- <hibernate-mapping package="entities">
- <!-- table per concrete (a. 具体的,实际的) -->
- <!-- 每一个具体类一张表 -->
- <!-- 虚拟选项为'true' -->
- <class name="Person" table="tb_person" abstract="true">
- <id column="id" name="id" type="java.lang.Integer">
- <!-- 主键的生成策略为'分配' -->
- <generator class="assigned"></generator>
- </id>
- <property column="name" name="name" type="string"></property>
- <property column="sex" name="sex" type="string"></property>
- <property column="age" name="age" type="java.lang.Integer"></property>
- <!--student具体类-->
- <union-subclass name="Student" table="tb_student">
- <property column="sno" name="sno" type="string"></property>
- <property column="school" name="school" type="string"></property>
- </union-subclass>
- <!--worker具体类-->
- <union-subclass name="Worker" table="tb_worker">
- <property column="no" name="no" type="string"></property>
- <property column="salary" name="salary" type="java.lang.Double"></property>
- </union-subclass>
- </class>
- </hibernate-mapping>
1.tph每个继承树一张表
mysql> show tables;
+-------------------+
| Tables_in_db_test |
+-------------------+
| tb_person |
+-------------------+
mysql> desc tb_person;
+---------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------+--------------+------+-----+---------+-------+
| id | int(11) | NO | PRI | NULL | |
| discram | varchar(255) | NO | | NULL | |
| name | varchar(255) | YES | | NULL | |
| age | int(11) | YES | | NULL | |
| sex | varchar(255) | YES | | NULL | |
| school | varchar(255) | YES | | NULL | |
| sno | varchar(255) | YES | | NULL | |
| no | varchar(255) | YES | | NULL | |
| salary | double | YES | | NULL | |
+---------+--------------+------+-----+---------+-------+
Person.hbm.xml
- <?xml version="1.0"?>
- <!DOCTYPE hibernate-mapping PUBLIC
- "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
- "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
- <hibernate-mapping package="entities">
- <!-- tph table per hierarchy 一个继承树一张表 -->
- <!-- 父类 -->
- <class name="Person" table="tb_person">
- <id column="id" name="id" type="java.lang.Integer">
- <!-- 主键生成策略为 '分配' -->
- <generator class="assigned"></generator>
- </id>
- <!-- 鉴定列,区分列 discriminator 鉴-->
- <discriminator column="discram" type="string"></discriminator>
- <property column="name" name="name" type="string"></property>
- <property column="age" name="age" type="java.lang.Integer"></property>
- <property column="sex" name="sex" type="string"></property>
- <!-- 子类,其鉴定列值为'stu'-->
- <subclass name="Student" discriminator-value="stu">
- <property column="school" name="school" type="string"></property>
- <property column="sno" name="sno" type="string"></property>
- </subclass>
- <!-- 子类,其鉴定列值为'worker'-->
- <subclass name="Worker" discriminator-value="worker">
- <property column="no" name="no" type="string"></property>
- <property column="salary" name="salary" type="java.lang.Double"></property>
- </subclass>
- </class>
- </hibernate-mapping>
1.tps每个子类一张表
mysql> show tables;
+-------------------+
| Tables_in_db_test |
+-------------------+
| tb_person |
| tb_student |
| tb_worker |
+-------------------+
mysql> desc tb_person;
+-------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+-------+
| id | int(11) | NO | PRI | NULL | |
| name | varchar(255) | YES | | NULL | |
| sex | varchar(255) | YES | | NULL | |
| age | int(11) | YES | | NULL | |
+-------+--------------+------+-----+---------+-------+
mysql> desc tb_student;
+-----------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------+--------------+------+-----+---------+-------+
| studentid | int(11) | NO | PRI | NULL | |
| sno | varchar(255) | YES | | NULL | |
| school | varchar(255) | YES | | NULL | |
+-----------+--------------+------+-----+---------+-------+
mysql> desc tb_worker;
+----------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+--------------+------+-----+---------+-------+
| workerid | int(11) | NO | PRI | NULL | |
| no | varchar(255) | YES | | NULL | |
| salary | varchar(255) | YES | | NULL | |
+----------+--------------+------+-----+---------+-------+
Person.hbm.xml
- <?xml version="1.0"?>
- <!DOCTYPE hibernate-mapping PUBLIC
- "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
- "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
- <hibernate-mapping package="entities">
- <!-- Person表 -->
- <class name="Person" table="tb_person">
- <id name="id">
- <!-- 父类的主键生成策略为‘分配’ -->
- <generator class="assigned"></generator>
- </id>
- <property name="name" type="string"></property>
- <property name="sex" type="string"></property>
- <property name="age" type="java.lang.Integer"></property>
- <!-- student表 -->
- <joined-subclass name="Student" table="tb_student">
- <key column="studentid"></key>
- <property column="sno" name="sno" type="string" ></property>
- <property column="school" name="school" type="string" ></property>
- </joined-subclass>
- <!-- worker表 -->
- <joined-subclass name="Worker" table="tb_worker">
- <key column="workerid"></key>
- <property column="no" name="no" type="string" ></property>
- <property column="salary" name="salary" type="string" ></property>
- </joined-subclass>
- </class>
- </hibernate-mapping>
方式一: 每个具体类一张表 (union-subclass) ,保存是子类完整信息 (table per
concrete )
建立关系模型原则:每个具体类对应一张表,有多少具体类就需要建立多少个独立的表
优缺点:这种设计方式符合关系模型的设计原则,但有表中存在重复字段的问题。如果需要对基类进行修改,则需要对基类以及该类的子类所对应的所有表都进行修改,映射的灵活性很大,子类可以包括基类属性在内的每一个属性进行单独配置,对于子类的查询只需要访问单独的表,对父类查询怎需要检索所有的表,对于单个对象持久话操作只需要处理一个表
方式二:整个的继承体系就用一张表(table per
hierarchy)
建立关系模型原则:描述一个继承关系只用一张表
优缺点:首先表中引入的区分子类的字段,也就是包括了描述其他字段的字段。其次,如果某个子类的某个属性不能为空,那么在数据库一级不能设置该字段not null(非空),维护起来方便,只需要修改一个表,灵活性差,表中冗余字段会随着子类的增多而越来越多,在任何情况下,都只需处理一个表,对于单个对象的持久话操作只需要处理一个表
方式三: 每个子类一张表,存放子类所特有的属性(table per subclass)
建立关系模型原则:每个子类使用一张表,但这些子类所对应的表都关联到基类所对应的表中
优缺点:这种设计方式完全符合关系模型的设计原则,且不存在冗余,维护起来比较方便,对每个类的修改只需要修改其所对应的表,灵活性很好,完全是参照对象继承的方式进行配置,对于父类的查询需要使用左外链接,对于子类查询需要使用内链接,对于子类的持久话至少要处理两个表