现在有四个类Company、Employee、SalaryEmployee、HourlyEmployee,其中Employee是SalaryEmployee、HourlyEmployee的父类
类的实现代码如下:
public class Company implements java.io.Serializable { // Fields private Integer id; private String name; private Set Employees = new HashSet(0); }
public class Employee implements java.io.Serializable { // Fields private Integer id; private String name; private Company company; }
public class HourlyEmployee extends Employee implements java.io.Serializable { // Fields private Double rate; }
public class SalaryEmployee extendsEmployee implements java.io.Serializable { // Fields private Double salary; }这四个类都省略了getter/setter方法,并且都是用Hibernate反向机制自动生成的。
该种实现Hibernate继承映射策略——每个具体对应一张表,上述的具体类就是HourlyEmployee和SalaryEmployee
首先设计下数据库,具体如下图:
company表
hourly_employee表
salary_employee表
hourly_employee和salary_employee表中的字段company_id为外键,参照company表中的id
配置company.hbm.xml文件
<?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"> <!-- Mapping file autogenerated by MyEclipse Persistence Tools --> <hibernate-mapping> <class name="com.xkey.hibernate.bean.Company" table="company" catalog="hibernate"> <id name="id" type="java.lang.Integer"> <column name="id" /> <generator class="identity" /> </id> <property name="name" type="java.lang.String"> <column name="name" length="128" not-null="true" /> </property> <set name="Employee1s" inverse="true" cascade="all" lazy="true"> <key> <column name="company_id" not-null="true" /> </key> <one-to-many class="com.xkey.hibernate.bean.Employee1" /> </set> </class> </hibernate-mapping>
<?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"> <!-- Mapping file autogenerated by MyEclipse Persistence Tools --> <hibernate-mapping> <class name="com.xkey.hibernate.bean.Employee1"> <id name="id" type="java.lang.Integer"> <column name="id" /> <generator class="increment" /> </id> <property name="name" type="java.lang.String"> <column name="name" length="128" not-null="true" /> </property> <many-to-one name="company" class="com.xkey.hibernate.bean.Company" fetch="select"> <column name="company_id" not-null="true" /> </many-to-one> <union-subclass name="com.xkey.hibernate.bean.HourlyEmployee1" table="hourly_employee1" extends="com.xkey.hibernate.bean.Employee1"> <property name="rate" type="java.lang.Double"> <column name="rate" precision="10" scale="5"></column> </property> </union-subclass> <union-subclass name="com.xkey.hibernate.bean.SalaryEmployee1" table="salary_employee1" extends="com.xkey.hibernate.bean.Employee1"> <property name="salary" type="java.lang.Double"> <column name="salary" precision="10" scale="5"></column> </property> </union-subclass> </class> </hibernate-mapping>Employee1.hbm.xml中hourly_employee表和salary_employee表拥有的公共字段使用<property>,外键使用<many-to-one>,对于每个表特定的字段就使用<union-subclass>
具体就看上面的配置文件就可以了。
这里需要注意的是:使用<union-subclass>那么generator就不能使用class="identity",否则会报错:Cannot use identity column key generation with <union-subclass> mapping
还有一点就是<class name="com.xkey.hibernate.bean.Employee1">如果添加abstract属性的话,如果abstract="true"那么将不会生成表结构,如果abstract="false"那么将不会插入数据。个人觉得这个属性还是不要加的好。
在具体insert数据的时候会出现如下问题:
Company company = new Company("xkey",new HashSet()); HourlyEmployee1 employee1 = new HourlyEmployee1("xukai",company,12.5); SalaryEmployee1 employee2 = new SalaryEmployee1("color",company,10000.0); company.getEmployee1s().add(employee1); company.getEmployee1s().add(employee2); CompanyDAO dao = new CompanyDAO(); dao.save(company);上面这段代码就是company、hourly_employee、salary_employee个插入一条数据,但是都是参照同一个company,这里在insert后会发现hourly_employee、salary_employee表中的主键id是不连续,具体是什么原因就需要去问Hibernate了,不用说也应该知道,问题肯定在session那里。
下图是我连续执行两次上述代码的结果
由于只有EmployeeDAO这一个DAO层访问数据库的方法,所以在查询的时候会很蛋疼,如果按照id来查询,那么查询出来的值究竟是hourly_employee表的数据还是salary_employee表呢,解决这个就需要调用返回值的类型来判断下。
综上所述,此种实现继承映射的方法个人觉得很蛋疼,还不如hourly_employee、salary_employee表个搞一个hbm.xml文件呢,这样对数据库的操作都将很方便,并且数据库存储的开销也和上面的方法相同,所以这种解决映射问题的方法不可取,大家就使用平常的方法就可以了。
还有其他两种解决映射问题的方法,将在后面介绍。
上面都是本人自己的见解,刚刚接触Hibernate,如果有说的不对的地方还望大家指正。