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>
二、使用 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 }
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 }
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>
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; } }
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 }
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>
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 }
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 }
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>
3、备注:
1、采用 union-subclass 元素可以实现将每一个实体对象映射到一个独立的表中;
2、子类增加的属性可以有非空约束,子类实例的数据仅保存在子类表中;
3、使用 union-subclass 映射策略,既不需要使用鉴别者列,也无须使用 key 元素来映射共有主键;
4、使用 union-subclass 映射策略是不可使用 identity 的主键生成策略;
5、插入操作:对于子类对象只需把记录插入到一张数据表中;
6、查询操作:查询父类记录,需把父表和子表记录汇总到一起再做查询,性能稍差。查询子类记录, 也只需要查询一张数据表;
4、优缺点:
优点:
1. 无需使用辨别者列.
2. 子类独有的字段能添加非空约束.
缺点:
1. 存在冗余的字段
2. 若更新父表的字段, 则更新的效率较低
建议使用 joined-subclass 进行映射或者使用 union-subclass 进行映射