hibernate 继承映射

在域模型中,类与类之间除了关联关系和聚集关系,还可以存在继承关系,在下图所示的域模型中,Deparment类和Employee类之间为一对多的双向关联关系,Employee类有两个子类:Skiller类和Sales类。由于Java只允许一个类最多有一个直接的父类,因此Employee类、 Skiller类和Sales类构成了一棵继承关系树。
hibernate 继承映射
 在面向对象的范畴中,还存在多态的概念,多态建立在继承关系的基础上。简单地理解,多态是指当一个Java应用变量被声明为Employee类时,这个变量实际上既可以引用Employee类自己的实例,Skiller类的实例,也可以引用Sales类的实例。Department类的getEmps()方法通过Hibernate API从数据库中检索出所有Employee对象。getEmps()方法返回的集合既可以包含Employee类自己的实例,Skiller类的实例,也可以引用Sales类的实例。,这种查询被称为多态查询。数据库表之间并不存在继承关系,那么如何把域模型的继承关系映射到关系数据模型中呢?hibernate有以下三种映射方式:

继承关系树的根类对应一个表:对关系数据模型进行非常规设计,在数据库表中加入额外的区分子类型的字段。通过这种方式,可以使关系数据模型支持继承关系和多态。

继承关系树的每个类对应一个表(子类与父类通过外键关联):在关系数据模型中用外键参照关系来表示继承关系。

继承关系树的每个具体类对应一个表:关系数据模型完全不支持域模型中的继承关系和多态。

1.继承关系树的根类对应一个表employee(整个继承树一张表):

employee的表结构如下所示:

mysql> desc employee;
+------------+--------------+------+-----+---------+----------------+
| Field      | Type         | Null | Key | Default | Extra          |
+------------+--------------+------+-----+---------+----------------+
| id         | int(11)      | NO   | PRI | NULL    | auto_increment |
| type       | int(11)      | NO   |     | NULL    |                |
| name       | varchar(255) | YES  | UNI | NULL    |                |
| depart_id  | int(11)      | YES  | MUL | NULL    |                |
| skill       | varchar(255) | YES  |     | NULL    |                |
| saleAmount | int(11)      | YES  |     | NULL    |                |
+------------+--------------+------+-----+---------+----------------+

实体类Department和Employee请参看我前面的文章,Skiller和Sales分别如下所示:

Java代码 复制代码  收藏代码
  1. package com.reiyen.hibernate.domain;   
  2.   
  3. public class Skiller extends Employee {   
  4.   
  5.     private String skill;   
  6. //setter和getter方法   
  7. }  
package com.reiyen.hibernate.domain;

public class Skiller extends Employee {

	private String skill;
//setter和getter方法
}
 
Java代码 复制代码  收藏代码
  1. package com.reiyen.hibernate.domain;   
  2. public class Sales extends Employee {   
  3.   
  4.     private int saleAmount;   
  5. //setter和getter方法   
  6. }  
package com.reiyen.hibernate.domain;
public class Sales extends Employee {

	private int saleAmount;
//setter和getter方法
}

 Employee.hbm.xml映射文件如下:

Xml代码 复制代码  收藏代码
  1. <?xml version="1.0"?>  
  2. <!DOCTYPE hibernate-mapping PUBLIC    
  3.     "-//Hibernate/Hibernate Mapping DTD 3.0//EN"   
  4.     "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">  
  5. <hibernate-mapping package="com.reiyen.hibernate.domain">  
  6.     <class name="Employee" discriminator-value="0">  
  7.         <id name="id">  
  8.             <generator class="native" />  
  9.         </id>  
  10.         <!--discriminator(鉴别器):缺省类型为string,这里指定为int类型 -->  
  11.         <discriminator column="type" type="int"></discriminator>  
  12.         <property name="name" unique="true"/>  
  13.         <!-- name="department" 这个名称必须与Employee中的属性名一致. 设置了column="depart_id",默认它会去department中找id与depart_id值相等的对象.如果要找name的值与depart_id相等的对象,则可以设置property-ref="name" -->  
  14.         <many-to-one name="department" column="depart_id" />  
  15.         <subclass name="Skiller" discriminator-value="1">  
  16.             <property name="skill" />  
  17.         </subclass>  
  18.         <subclass name="Sales" discriminator-value="2">  
  19.             <property name="saleAmount" />  
  20.         </subclass>  
  21.     </class>  
  22. </hibernate-mapping>  
<?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="com.reiyen.hibernate.domain">
	<class name="Employee" discriminator-value="0">
		<id name="id">
			<generator class="native" />
		</id>
		<!--discriminator(鉴别器):缺省类型为string,这里指定为int类型 -->
		<discriminator column="type" type="int"></discriminator>
		<property name="name" unique="true"/>
		<!-- name="department" 这个名称必须与Employee中的属性名一致. 设置了column="depart_id",默认它会去department中找id与depart_id值相等的对象.如果要找name的值与depart_id相等的对象,则可以设置property-ref="name" -->
		<many-to-one name="department" column="depart_id" />
		<subclass name="Skiller" discriminator-value="1">
			<property name="skill" />
		</subclass>
		<subclass name="Sales" discriminator-value="2">
			<property name="saleAmount" />
		</subclass>
	</class>
</hibernate-mapping>
 

 测试类如下:

Java代码 复制代码  收藏代码
  1. public class Many2One {   
  2.   
  3.     public static void main(String[] args) {   
  4.         add();   
  5.          query(1);//1   
  6.     }   
  7.   
  8.     static void query(int empId) {   
  9.         Session s = null;   
  10.         Transaction tx = null;   
  11.         try {   
  12.             s = HibernateUtil.getSession();   
  13.             tx = s.beginTransaction();   
  14.             Employee emp = (Employee) s.get(Employee.class, empId);//2   
  15.             System.out.println(emp.getClass());   
  16.             tx.commit();   
  17.         } finally {   
  18.             if (s != null)   
  19.                 s.close();   
  20.         }   
  21.     }   
  22.   
  23.   
  24.   
  25.     static void add() {   
  26.         Session s = null;   
  27.         Transaction tx = null;   
  28.         try {   
  29.             Department depart = new Department();   
  30.             depart.setName("department name");   
  31.                
  32.             Employee employee1 = new Employee();   
  33.             employee1.setDepartment(depart); //1 对象模型:建立两个对象的关联    
  34.             employee1.setName("employee1 name1");   
  35.                
  36.             Skiller employee2 = new Skiller();   
  37.             employee2.setDepartment(depart); //2 对象模型:建立两个对象的关联    
  38.             employee2.setName("employee2 name2");   
  39.             employee2.setSkill("j2se");   
  40.                
  41.             Sales employee3 = new Sales();   
  42.             employee3.setDepartment(depart); //2 对象模型:建立两个对象的关联    
  43.             employee3.setName("employee3 name3");   
  44.             employee3.setSaleAmount(1000);   
  45.                
  46.             s = HibernateUtil.getSession();   
  47.             tx = s.beginTransaction();   
  48.             s.save(depart);   
  49.             s.save(employee1);   
  50.             s.save(employee2);   
  51.             s.save(employee3);   
  52.             tx.commit();   
  53.         } finally {   
  54.             if (s != null)   
  55.                 s.close();   
  56.         }   
  57.     }   
  58. }  
public class Many2One {

	public static void main(String[] args) {
		add();
		 query(1);//1
	}

	static void query(int empId) {
		Session s = null;
		Transaction tx = null;
		try {
			s = HibernateUtil.getSession();
			tx = s.beginTransaction();
			Employee emp = (Employee) s.get(Employee.class, empId);//2
			System.out.println(emp.getClass());
			tx.commit();
		} finally {
			if (s != null)
				s.close();
		}
	}



	static void add() {
		Session s = null;
		Transaction tx = null;
		try {
			Department depart = new Department();
			depart.setName("department name");
			
			Employee employee1 = new Employee();
			employee1.setDepartment(depart); //1 对象模型:建立两个对象的关联 
			employee1.setName("employee1 name1");
			
			Skiller employee2 = new Skiller();
			employee2.setDepartment(depart); //2 对象模型:建立两个对象的关联 
			employee2.setName("employee2 name2");
			employee2.setSkill("j2se");
			
			Sales employee3 = new Sales();
			employee3.setDepartment(depart); //2 对象模型:建立两个对象的关联 
			employee3.setName("employee3 name3");
			employee3.setSaleAmount(1000);
			
			s = HibernateUtil.getSession();
			tx = s.beginTransaction();
			s.save(depart);
			s.save(employee1);
			s.save(employee2);
			s.save(employee3);
			tx.commit();
		} finally {
			if (s != null)
				s.close();
		}
	}
}

 程序运行后,控制台打印信息如下所示:

Hibernate: insert into Department (name) values (?)
Hibernate: insert into Employee (name, depart_id, type) values (?, ?, 0)
Hibernate: insert into Employee (name, depart_id, skill, type) values (?, ?, ?, 1)
Hibernate: insert into Employee (name, depart_id, saleAmount, type) values (?, ?, ?, 2)
Hibernate: select employee0_.id as id1_0_, employee0_.name as name1_0_, employee0_.depart_id as depart4_1_0_, employee0_.skill as skill1_0_, employee0_.saleAmount as saleAmount1_0_, employee0_.type as type1_0_ from Employee employee0_ where employee0_.id=?
class com.reiyen.hibernate.domain.Employee

employee表中记录如下所示:

mysql> select * from employee;
+----+------+-----------------+-----------+-------+------------+
| id | type | name            | depart_id | skill | saleAmount |
+----+------+-----------------+-----------+-------+------------+
|  1 |    0 | employee1 name1 |         1 | NULL  |       NULL |
|  2 |    1 | employee2 name2 |         1 | j2se  |       NULL |
|  3 |    2 | employee3 name3 |         1 | NULL  |       1000 |
+----+------+-----------------+-----------+-------+------------+
3 rows in set (0.00 sec)

将测试代码中注释为1的语句改成:

Java代码 复制代码  收藏代码
  1. query(2);  
query(2);

再运行,控制台打印的class如下所示(因为hibernate支持多态查询): class com.reiyen.hibernate.domain.Skiller

打印的查询语句还是如上面所示的没有改变。

在上面修改的基础上,再将测试代码中注释为2的语句改成:

Java代码 复制代码  收藏代码
  1. Employee emp = (Employee) s.get(Skiller.class, empId);  
Employee emp = (Employee) s.get(Skiller.class, empId);

 再运行,则控制台打印的查询语句为:

Hibernate: select skiller0_.id as id1_0_, skiller0_.name as name1_0_, skiller0_.depart_id as depart4_1_0_, skiller0_.skill as skill1_0_ from Employee skiller0_ where skiller0_.id=? and skiller0_.type=1
class com.reiyen.hibernate.domain.Skiller

优点:操作效率高

缺点:如果说给employee增加子类的话,必须修改表结构,给表结构增加一个字段;同时表中对应子类的字段不能有非空约束.

2.继承关系树的每子类对应一个表(joined-subclass),表结构如下所示:


hibernate 继承映射
 修改Employee.hbm.xml映射文件如下所示:

Xml代码 复制代码  收藏代码
  1. <?xml version="1.0"?>  
  2. <!DOCTYPE hibernate-mapping PUBLIC    
  3.     "-//Hibernate/Hibernate Mapping DTD 3.0//EN"   
  4.     "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">  
  5. <hibernate-mapping package="com.reiyen.hibernate.domain">  
  6.     <class name="Employee">  
  7.         <id name="id">  
  8.             <generator class="native" />  
  9.         </id>  
  10.         <property name="name" unique="true"/>  
  11.         <!-- name="department" 这个名称必须与Employee中的属性名一致. 设置了column="depart_id",默认它会去department中找id与depart_id值相等的对象.如果要找name的值与depart_id相等的对象,则可以设置property-ref="name" -->  
  12.         <many-to-one name="department" column="depart_id" />  
  13.         <joined-subclass name="Skiller" table="skiller">  
  14.          <key column="employee_id" />  
  15.          <property name="skill" />  
  16.         </joined-subclass>  
  17.         <joined-subclass name="Sales" table="sales">  
  18.          <key column="employee_id" />  
  19.          <property name="saleAmount" column="sale_amount" />  
  20.         </joined-subclass>  
  21.     </class>  
  22. </hibernate-mapping>  
<?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="com.reiyen.hibernate.domain">
	<class name="Employee">
		<id name="id">
			<generator class="native" />
		</id>
		<property name="name" unique="true"/>
		<!-- name="department" 这个名称必须与Employee中的属性名一致. 设置了column="depart_id",默认它会去department中找id与depart_id值相等的对象.如果要找name的值与depart_id相等的对象,则可以设置property-ref="name" -->
		<many-to-one name="department" column="depart_id" />
		<joined-subclass name="Skiller" table="skiller">
		 <key column="employee_id" />
		 <property name="skill" />
		</joined-subclass>
		<joined-subclass name="Sales" table="sales">
		 <key column="employee_id" />
		 <property name="saleAmount" column="sale_amount" />
		</joined-subclass>
	</class>
</hibernate-mapping>

 测试类不变,只是将测试代码中注释为1的语句改成:

Java代码 复制代码  收藏代码
  1. query(2);  
query(2);

则控制台打印的信息如下所示:

Hibernate: insert into Department (name) values (?)
Hibernate: insert into Employee (name, depart_id) values (?, ?)
Hibernate: insert into Employee (name, depart_id) values (?, ?)
Hibernate: insert into skiller (skill, employee_id) values (?, ?)

Hibernate: insert into Employee (name, depart_id) values (?, ?)
Hibernate: insert into sales (sale_amount, employee_id) values (?, ?)
Hibernate: select employee0_.id as id1_0_, employee0_.name as name1_0_, employee0_.depart_id as depart3_1_0_, employee0_1_.skill as skill2_0_, employee0_2_.sale_amount as sale2_3_0_, case when employee0_1_.employee_id is not null then 1 when employee0_2_.employee_id is not null then 2 when employee0_.id is not null then 0 end as clazz_0_ from Employee employee0_ left outer join skiller employee0_1_ on employee0_.id=employee0_1_.employee_id left outer join sales employee0_2_ on employee0_.id=employee0_2_.employee_id where employee0_.id=?
class com.reiyen.hibernate.domain.Skiller
 从打印的SQL语句可以看出,此时,如果保存的是Employee对象的子类的实例的话,则要在两张表中保存记录;如果查询的是子类对象的话,是三张表关联在一起进行查询。

 

在上面修改的基础上,再将测试代码中注释为2的语句改成:

Java代码 复制代码  收藏代码
  1. Employee emp = (Employee) s.get(Skiller.class, empId);  
Employee emp = (Employee) s.get(Skiller.class, empId);

 再运行,则控制台打印的查询语句为:

Hibernate: select skiller0_.employee_id as id1_0_, skiller0_1_.name as name1_0_, skiller0_1_.depart_id as depart3_1_0_, skiller0_.skill as skill2_0_ from skiller skiller0_ inner join Employee skiller0_1_ on skiller0_.employee_id=skiller0_1_.id where skiller0_.employee_id=?
此时只关联两张表查询。

数据库中表记录如下所示:

mysql> select * from employee;
+----+-----------------+-----------+
| id | name            | depart_id |
+----+-----------------+-----------+
|  1 | employee1 name1 |         1 |
|  2 | employee2 name2 |         1 |
|  3 | employee3 name3 |         1 |
+----+-----------------+-----------+
3 rows in set (0.00 sec)

mysql> select * from skiller;
+-------------+-------+
| employee_id | skill |
+-------------+-------+
|           2 | j2se  |
+-------------+-------+
1 row in set (0.00 sec)

mysql> select * from sales;
+-------------+-------------+
| employee_id | sale_amount |
+-------------+-------------+
|           3 |        1000 |
+-------------+-------------+
1 row in set (0.00 sec)

 

3.混合使用,假设如果Sales的属性很多,而Skiller的属性很少,这时可以混使用“一个类继承体系一张表”和“每个子类一张表”,表结构如下所示:



 Employee.hbm.xml映射文件如下所示:

Xml代码 复制代码  收藏代码
  1. <?xml version="1.0"?>  
  2. <!DOCTYPE hibernate-mapping PUBLIC    
  3.     "-//Hibernate/Hibernate Mapping DTD 3.0//EN"   
  4.     "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">  
  5. <hibernate-mapping package="com.reiyen.hibernate.domain">  
  6.     <class name="Employee" discriminator-value="0">  
  7.         <id name="id">  
  8.             <generator class="native" />  
  9.         </id>  
  10.         <discriminator column="type" type="int" />  
  11.         <property name="name" unique="true" />  
  12.         <!-- name="department" 这个名称必须与Employee中的属性名一致. 设置了column="depart_id",默认它会去department中找id与depart_id值相等的对象.如果要找name的值与depart_id相等的对象,则可以设置property-ref="name" -->  
  13.         <many-to-one name="department" column="depart_id" />  
  14. <!--如果discriminator-value没有显式的给定值的话,则与name属性的值保持一致,即为Skiller -->         
  15. <subclass name="Skiller" discriminator-value="1">  
  16.             <property name="skill" />  
  17.         </subclass>  
  18.         <subclass name="Sales" discriminator-value="2">  
  19.             <join table="sales">  
  20.                 <key column="employee_id" />  
  21.                 <property name="saleAmount" column="sale_amount" />  
  22.             </join>  
  23.         </subclass>  
  24.     </class>  
  25. </hibernate-mapping>  
<?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="com.reiyen.hibernate.domain">
	<class name="Employee" discriminator-value="0">
		<id name="id">
			<generator class="native" />
		</id>
		<discriminator column="type" type="int" />
		<property name="name" unique="true" />
		<!-- name="department" 这个名称必须与Employee中的属性名一致. 设置了column="depart_id",默认它会去department中找id与depart_id值相等的对象.如果要找name的值与depart_id相等的对象,则可以设置property-ref="name" -->
		<many-to-one name="department" column="depart_id" />
<!--如果discriminator-value没有显式的给定值的话,则与name属性的值保持一致,即为Skiller -->		
<subclass name="Skiller" discriminator-value="1">
			<property name="skill" />
		</subclass>
		<subclass name="Sales" discriminator-value="2">
			<join table="sales">
				<key column="employee_id" />
				<property name="saleAmount" column="sale_amount" />
			</join>
		</subclass>
	</class>
</hibernate-mapping>

 此时测试类不变,只是将测试代码中注释为1的语句改成:

Java代码 复制代码  收藏代码
  1. query(2);  
query(2);

然后在上面的基础上运行原程序,则控制台会打印出如下异常信息:

Hibernate: insert into Department (name) values (?)
Hibernate: insert into Employee (name, depart_id, type) values (?, ?, 0)
Exception in thread "main" org.hibernate.exception.SQLGrammarException: could not insert: [com.reiyen.hibernate.domain.Employee]

Caused by: com.mysql.jdbc.exceptions.MySQLSyntaxErrorException: Unknown column 'type' in 'field list'

这是因为我在hibernate.cfg.xml配置文件中配置了此项:

Xml代码 复制代码  收藏代码
  1. <property name="hbm2ddl.auto">create</property>  
<property name="hbm2ddl.auto">create</property>

 所以在此次程序运行时,会删除数据库中的employee表,sales表,而employee表中有skiller表的外键关联,所以不能删除employee数据表了,所以抛出了上面的异常。此时你再查看数据库表,如下所示 :

mysql> select * from employee;
+----+-----------------+-----------+
| id | name            | depart_id |
+----+-----------------+-----------+
|  1 | employee1 name1 |         1 |
|  2 | employee2 name2 |         1 |
|  3 | employee3 name3 |         1 |
+----+-----------------+-----------+
3 rows in set (0.00 sec)

mysql> select * from skiller;
+-------------+-------+
| employee_id | skill |
+-------------+-------+
|           2 | j2se  |
+-------------+-------+
1 row in set (0.00 sec)

mysql> select * from sales;
Empty set (0.00 sec)

所以得先手动删除skiller数据表,然后再来运行程序:

 

如果Employee.hbm.xml配置文件中

Xml代码 复制代码  收藏代码
  1. <subclass name="Skiller" >  
<subclass name="Skiller" >

不配置discriminator-value="1",则会抛出如下异常:

java.lang.ExceptionInInitializerError

Caused by: org.hibernate.MappingException: Could not format discriminator value to SQL string

因为如果discriminator-value没有显式的给定值的话,则与name属性的值保持一致,即为Skiller ,所以会抛出如上异常!

 

4.继承关系树的每个具体类对应一个表(union-subclass)

表结构如下所示:


Employee.hbm.xml映射文件如下:

Xml代码 复制代码  收藏代码
  1. <?xml version="1.0"?>  
  2. <!DOCTYPE hibernate-mapping PUBLIC    
  3.     "-//Hibernate/Hibernate Mapping DTD 3.0//EN"   
  4.     "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">  
  5. <hibernate-mapping package="com.reiyen.hibernate.domain">  
  6.     <class name="Employee">  
  7.         <id name="id">  
  8.             <generator class="hilo" />  
  9.         </id>  
  10.         <property name="name" unique="true" />  
  11.         <many-to-one name="department" column="depart_id" />  
  12.         <union-subclass name="Skiller" table="skiller">  
  13.          <property name="skill" />  
  14.         </union-subclass>  
  15.         <union-subclass name="Sales" table="sales">  
  16.          <property name="saleAmount" column="sale_amount" />  
  17.         </union-subclass>  
  18.     </class>  
  19. </hibernate-mapping>  
<?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="com.reiyen.hibernate.domain">
	<class name="Employee">
		<id name="id">
			<generator class="hilo" />
		</id>
		<property name="name" unique="true" />
		<many-to-one name="department" column="depart_id" />
		<union-subclass name="Skiller" table="skiller">
		 <property name="skill" />
		</union-subclass>
		<union-subclass name="Sales" table="sales">
		 <property name="saleAmount" column="sale_amount" />
		</union-subclass>
	</class>
</hibernate-mapping>

 此时主键增长不能再是:

Xml代码 复制代码  收藏代码
  1. <generator class="native" />  
<generator class="native" />

因为如果使用native的话三张表会产生相同的id值,这样当根据id查询Employee时就会出错了。所以如果你配置成native时会抛出如下异常(因为Employee实体类中id对应 的是int了,所以在此使用hilo(高低位)主键生成方式):

org.hibernate.MappingException: Cannot use identity column key generation with <union-subclass> mapping for: com.reiyen.hibernate.domain.Skiller

 

运行测试程序后,此时控制台打印信息如下所示:

Hibernate: insert into Department (name) values (?)
Hibernate: insert into Employee (name, depart_id, id) values (?, ?, ?)
Hibernate: insert into skiller (name, depart_id, skill, id) values (?, ?, ?, ?)
Hibernate: insert into sales (name, depart_id, sale_amount, id) values (?, ?, ?, ?)
Hibernate: select employee0_.id as id1_0_, employee0_.name as name1_0_, employee0_.depart_id as depart3_1_0_, employee0_.skill as skill2_0_, employee0_.sale_amount as sale1_3_0_, employee0_.clazz_ as clazz_0_ from ( select id, null as sale_amount, depart_id, null as skill, name, 0 as clazz_ from Employee union select id, null as sale_amount, depart_id, skill, name, 1 as clazz_ from skiller union select id, sale_amount, depart_id, null as skill, name, 2 as clazz_ from sales ) employee0_ where employee0_.id=?
class com.reiyen.hibernate.domain.Skiller

执行查询时,首先使用子查询,在子查询中使用union将三张表的结果全成一张表,然后再在合成的结果集中进行查询。

如果Employee是一个抽象类, 你不想 在数据表中对应相应的数据表,则可以设置abstract="true" .如下所示:

Xml代码 复制代码  收藏代码
  1. <class name="Employee" abstract="true" >  
<class name="Employee" abstract="true" >

  此外,如果继承关系中有接口,可以把它当作抽象类对待。

三种映射方式的比较和选择
为了方便说明为三种方式按顺序标号为[1]整个继承树一张表;[2]每子类对应一个表(joined-subclass);[4]每个具体类对应一个表(union-subclass)。
1、复杂度:

    [1]简单;
    [2]表较多且之间有外键约束;

    [4]包含重复字段;
2、查询性能:

    [1]效率高;
    [2]需要表内连接或左外连接;

    [4]若查询父类需查所有子类表;
3、可维护性:

    [1]只需修改一个表;
    [2]若某个类属性变化只修改这个类对应的表;

    [4]若父类属性变化需要修改所有子类对应的表;
综上,选择时,可以参考以下原则:
1、子类属性不是非常多时,优先考虑[1],因为其性能最佳。
2、子类属性非常多,且对性能要求不是很严格时,优先考虑[2]

你可能感兴趣的:(Hibernate)