Hibernate的继承映射

一、创建Java工程,新建Lib文件夹,加入Hibernate和数据库(如MySql、Oracle、SqlServer等)的Jar包,创建 hibernate.cfg.xml 文件,并配置,配置项如下:

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <!DOCTYPE hibernate-configuration PUBLIC
 3         "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
 4         "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
 5 <hibernate-configuration>
 6     <session-factory>
 7     
 8         <!-- 配置连接数据库的基本信息 -->
 9         <property name="connection.username">root</property>
10         <property name="connection.password"></property>
11         <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
12         <!-- <property name="connection.url">jdbc:mysql:///mis</property> -->
13         <property name="connection.url">
14             <![CDATA[jdbc:mysql://localhost:3306/mis?useUnicode=true&characterEncoding=utf8]]>
15         </property>
16 
17 
18         <!-- 配置 hibernate 的基本信息 -->
19         <!-- hibernate 所使用的数据库方言 -->
20         <property name="dialect">org.hibernate.dialect.MySQL5Dialect</property>
21 
22         <!-- 执行操作时是否在控制台打印 SQL -->
23         <property name="show_sql">true</property>
24 
25         <!-- 是否对 SQL 进行格式化 -->
26         <property name="format_sql">true</property>
27 
28         <!-- 指定自动生成数据表的策略 -->
29         <property name="hbm2ddl.auto">update</property>
30         
31         <!-- 设置 Hibernate 的事务隔离级别 2:读已提交的记录-->
32         <property name="connection.isolation">2</property>
33         
34         <!-- 删除对象后, 使其 OID 置为 null -->
35         <property name="use_identifier_rollback">true</property>
36         
37         <!-- 配置 C3P0 数据源 -->
38         <property name="hibernate.c3p0.max_size">10</property>
39         <property name="hibernate.c3p0.min_size">5</property>
40         <property name="c3p0.acquire_increment">2</property>
41         
42         <property name="c3p0.idle_test_period">2000</property>
43         <property name="c3p0.timeout">2000</property>
44         
45         <property name="c3p0.max_statements">10</property>
46         
47         <!-- 设定 JDBC 的 Statement 读取数据的时候每次从数据库中取出的记录条数 -->
48         <property name="hibernate.jdbc.fetch_size">100</property>
49         
50         <!-- 设定对数据库进行批量删除,批量更新和批量插入的时候的批次大小 -->
51         <property name="jdbc.batch_size">30</property>
52 
53         <!-- 指定关联的 .hbm.xml 文件 -->    
54         <!--  
55         <mapping resource="com/mcs/hibernate/entities/onetoone/foreign/Manager.hbm.xml" />
56         <mapping resource="com/mcs/hibernate/entities/onetoone/foreign/Department.hbm.xml" />
57           -->
58         <!--   
59         <mapping resource="com/mcs/hibernate/entities/onetoone/primary/Manager.hbm.xml" />
60         <mapping resource="com/mcs/hibernate/entities/onetoone/primary/Department.hbm.xml" />
61          -->
62         <!-- 
63         <mapping resource="com/mcs/hibernate/entities/manytomany/Category.hbm.xml" />
64         <mapping resource="com/mcs/hibernate/entities/manytomany/Product.hbm.xml" />
65          -->
66         <!--  
67         <mapping resource="com/mcs/hibernate/entities/subclass/Person.hbm.xml" />
68          -->
69         <!--  
70         <mapping resource="com/mcs/hibernate/entities/joined/subclass/Person.hbm.xml" />
71          -->
72         
73         <mapping resource="com/mcs/hibernate/entities/union/subclass/Person.hbm.xml" />
74         
75 
76     </session-factory>
77 
78 </hibernate-configuration>
View Code

二、使用 subclass 进行映射

1、创建Java实体类: Person 和 Student

 1 package com.mcs.hibernate.entities.subclass;
 2 
 3 public class Person {
 4     
 5     private Integer id;
 6     private String name;
 7     private int age;
 8     
 9     public Integer getId() {
10         return id;
11     }
12     public void setId(Integer id) {
13         this.id = id;
14     }
15     public String getName() {
16         return name;
17     }
18     public void setName(String name) {
19         this.name = name;
20     }
21     public int getAge() {
22         return age;
23     }
24     public void setAge(int age) {
25         this.age = age;
26     }
27     
28     
29     
30 }
View Code
 1 package com.mcs.hibernate.entities.subclass;
 2 
 3 public class Student extends Person{
 4 
 5     private String school;
 6 
 7     public String getSchool() {
 8         return school;
 9     }
10 
11     public void setSchool(String school) {
12         this.school = school;
13     }
14     
15     
16     
17 }
View Code

2、根据实体类创建对应的 Person.hbm.xml文件

 1 <?xml version="1.0"?>
 2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
 3 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
 4 
 5 <hibernate-mapping package="com.mcs.hibernate.entities.subclass">
 6     <class name="Person" table="PERSONS" discriminator-value="PERSON">
 7         <id name="id" type="java.lang.Integer">
 8             <column name="ID" />
 9             <generator class="native" />
10         </id>
11         
12         <!-- 配置辨别者列 -->
13         <discriminator column="TYPE" type="string"></discriminator>
14         
15         <property name="name" type="java.lang.String">
16             <column name="NAME" />
17         </property>
18         <property name="age" type="int">
19             <column name="AGE" />
20         </property>
21         
22         <!-- 映射子类 Student, 使用 subclass 进行映射 -->
23         <subclass name="Student" discriminator-value="STUDENT">
24             <property name="school" type="string" column="SCHOOL"></property>
25         </subclass>
26         
27     </class>
28 </hibernate-mapping>
View Code

3、备注:

  1、父类和子类的实例全部保存在同一个表中,需要在该表内增加一列,使用该列来区分每行记录到低是哪个类的实例,这个列被称为辨别者列(discriminator)。

  2、使用 subclass 来映射子类,使用 class 或 subclass 的 discriminator-value 属性指定辨别者列的值。

  3、所有子类定义的字段都不能有非空约束。

  4、插入操作: 对于子类对象只需把记录插入到一张数据表中,辨别者列有 Hibernate 自动维护;

  5、查询操作: 查询父类记录, 只需要查询一张数据表,对于子类记录, 也只需要查询一张数据表。

4、缺点:

  1. 使用了辨别者列.
  2. 子类独有的字段不能添加非空约束.
  3. 若继承层次较深, 则数据表的字段也会较多.

三、使用 joined-subclass 进行映射

1、创建Java实体类: Person 和 Student 

package com.mcs.hibernate.entities.joined.subclass;

public class Person {
    
    private Integer id;
    private String name;
    private int 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 int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    
    
    
}
View Code
 1 package com.mcs.hibernate.entities.joined.subclass;
 2 
 3 public class Student extends Person{
 4 
 5     private String school;
 6 
 7     public String getSchool() {
 8         return school;
 9     }
10 
11     public void setSchool(String school) {
12         this.school = school;
13     }
14     
15     
16     
17 }
View Code

2、根据实体类创建对应的 Person.hbm.xml文件 

 1 <?xml version="1.0"?>
 2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
 3 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
 4 
 5 <hibernate-mapping package="com.mcs.hibernate.entities.joined.subclass">
 6     <class name="Person" table="PERSONS">
 7         <id name="id" type="java.lang.Integer">
 8             <column name="ID" />
 9             <generator class="native" />
10         </id>
11 
12         <property name="name" type="java.lang.String">
13             <column name="NAME" />
14         </property>
15         <property name="age" type="int">
16             <column name="AGE" />
17         </property>
18         
19         <joined-subclass name="Student" table="STUDENTS">
20             <key column="STUDENT_ID"></key>
21             <property name="school" type="string" column="SCHOOL"></property>
22         </joined-subclass>
23         
24     </class>
25 </hibernate-mapping>
View Code

3、备注:

  1、采用 joined-subclass 元素的继承映射可以实现每个子类一张表,父类实例保存在父类表中,子类实例由父类表和子类表共同存储;

  2、无须使用鉴别者列,但需要为每个子类使用 key 元素映射共有主键;

  3、子类增加的属性可以添加非空约束。

  4、插入操作: 对于子类对象至少需要插入到两张数据表中。

  5、查询操作: 查询父类记录, 做一个左外连接查询,对于子类记录, 做一个内连接查询。

4、优点:
  1. 不需要使用了辨别者列.
  2. 子类独有的字段能添加非空约束.
  3. 没有冗余的字段.

四、使用  union-subclass 进行映射

1、创建Java实体类: Person 和 Student  

 1 package com.mcs.hibernate.entities.union.subclass;
 2 
 3 public class Person {
 4     
 5     private Integer id;
 6     private String name;
 7     private int age;
 8     
 9     public Integer getId() {
10         return id;
11     }
12     public void setId(Integer id) {
13         this.id = id;
14     }
15     public String getName() {
16         return name;
17     }
18     public void setName(String name) {
19         this.name = name;
20     }
21     public int getAge() {
22         return age;
23     }
24     public void setAge(int age) {
25         this.age = age;
26     }
27     
28     
29     
30 }
View Code
 1 package com.mcs.hibernate.entities.union.subclass;
 2 
 3 public class Student extends Person{
 4 
 5     private String school;
 6 
 7     public String getSchool() {
 8         return school;
 9     }
10 
11     public void setSchool(String school) {
12         this.school = school;
13     }
14     
15     
16     
17 }
View Code

2、根据实体类创建对应的 Person.hbm.xml文件 

 1 <?xml version="1.0"?>
 2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
 3 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
 4 
 5 <hibernate-mapping package="com.mcs.hibernate.entities.union.subclass">
 6     <class name="Person" table="PERSONS">
 7         <id name="id" type="java.lang.Integer">
 8             <column name="ID" />
 9             <generator class="hilo" />
10         </id>
11 
12         <property name="name" type="java.lang.String">
13             <column name="NAME" />
14         </property>
15         <property name="age" type="int">
16             <column name="AGE" />
17         </property>
18         
19         <union-subclass name="Student" table="STUDENTS">
20             <property name="school" column="SCHOOL" type="string"></property>
21         </union-subclass> 
22         
23     </class>
24 </hibernate-mapping>
View Code

3、备注:

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

  2、子类增加的属性可以有非空约束,子类实例的数据仅保存在子类表中;

  3、使用 union-subclass 映射策略,既不需要使用鉴别者列,也无须使用 key 元素来映射共有主键;

  4、使用 union-subclass 映射策略是不可使用 identity 的主键生成策略;

  5、插入操作:对于子类对象只需把记录插入到一张数据表中;

  6、查询操作:查询父类记录,需把父表和子表记录汇总到一起再做查询,性能稍差。查询子类记录, 也只需要查询一张数据表;

4、优缺点:

  优点:
    1. 无需使用辨别者列.
    2. 子类独有的字段能添加非空约束.
  缺点:
    1. 存在冗余的字段
    2. 若更新父表的字段, 则更新的效率较低

建议使用 joined-subclass 进行映射或者使用 union-subclass 进行映射

posted @ 2015-10-29 13:23  小个子猫  阅读(405)  评论(0编辑  收藏  举报