精通Hibernate映射继承关系之四
2007-12-23 12:33:47 来源:WEB开发网核心提示:在这种映射方式下,继承关系树的每个类以及接口都对应一个表,精通Hibernate映射继承关系之四,在本例中,需要创建EMPLOYEES、HE和SE表,每保存一个HourlyEmployee对象,需要分别向EMPLOYEES表和HE表插入一条记录,如图14-6所示,EMPLOYEES表仅包含和Employee类的属性对应
在这种映射方式下,继承关系树的每个类以及接口都对应一个表。在本例中,需要创建EMPLOYEES、HE和SE表。
如图14-6所示,EMPLOYEES表仅包含和Employee类的属性对应的字段,HE表仅包含和HourlyEmployee类的属性对应的字段,SE表仅包含和SalariedEmployee类的属性对应的字段。此外,HE表和SE表都以EMPLOYEE_ID字段作为主键,该字段还同时作为外键参照EMPLOYEES表。
从Company类到Employee类是多态关联,由于关系数据模型描述了Employee类和它的两个子类的继承关系,因此可以映射Company类的employees集合。例程14-7是Company.hbm.xml文件的代码,该文件不仅映射了Company类的id和name属性,还映射了它的employees集合。
例程14-7 Company.hbm.xml
<hibernate-mapping > <class name="mypack.Company" table="COMPANIES" > <id name="id" type="long" column="ID"> <generator class="increment"/> </id> <PRoperty name="name" type="string" column="NAME" /> <set name="employees" inverse="true" lazy="true" > <key column="COMPANY_ID" /> <one-to-many class="mypack.Employee" /> </set> </class> </hibernate-mapping>
Employee.hbm.xml文件用于把Employee类映射到EMPLOYEES表,在这个映射文件中,除了需要映射Employee类本身的属性,还需要在
例程14-8 Employee.hbm.xml
<hibernate-mapping > <class name="mypack.Employee" table="EMPLOYEES"> <id name="id" type="long" column="ID"> <generator class="increment"/> </id> <property name="name" type="string" column="NAME" /> <many-to-one name="company" column="COMPANY_ID" class="mypack.Company" /> <joined-subclass name="mypack.HourlyEmployee" table="HOURLY_EMPLOYEES" > <key column="EMPLOYEE_ID" /> <property name="rate" column="RATE" type="double" /> </joined-subclass> <joined-subclass name="mypack.SalariedEmployee" table="SALARIED_EMPLOYEES" > <key column="EMPLOYEE_ID" /> <property name="salary" column="SALARY" type="double" /> </joined-subclass> </class> </hibernate-mapping>
在Employee.hbm.xml文件中,两个
由于HourlyEmployee类和SalariedEmployee类没有单独的映射文件,因此在初始化Hibernate时,只需向Configuration对象中加入Company类和Employee类:
Configuration config = new Configuration(); config.addClass(Company.class) .addClass(Employee.class);
也可以在单独的映射文件中配置
<hibernate-mapping > <joined-subclass name="mypack.HourlyEmployee" table="HOURLY_EMPLOYEES" extends="mypack.Employee" > …… </joined-class> <hibernate-mapping >
由于HourlyEmployee类的映射代码不位于Employee.hbm.xml文件中,因此在初始化Hibernate时,不仅需要向Configuration对象中加入Company类和Employee类,还需要加入HourlyEmployee类,并且必须先加入Employee父类,再加入HourlyEmployee子类:
Configuration config = new Configuration(); config.addClass(Company.class) .addClass(Employee.class) .addClass(HourlyEmployee.class);
如果颠倒加入Employee类和HourlyEmployee子类的顺序,Hibernate在执行addClass()方法时会抛出HibernateMappingException。
14.3.2 操纵持久化对象 这种映射方式支持多态查询,对于以下查询语句:
List employees=session.find("from Employee");
Hibernate会检索出所有的HourlyEmployee对象和SalariedEmployee对象。此外,也可以单独查询Employee类的两个子类的实例,例如:
List hourlyEmployees=session.find("from HourlyEmployee");
本节的范例程序位于配套光盘的sourcecode\chapter14\14.3目录下,运行该程序前,需要在SAMPLEDB数据库中手工创建COMPANIES表、EMPLOYEES表、HE表和SE表,然后加入测试数据,相关的SQL脚本文件为\14.3\schema\sampledb.sql。
在DOS命令行下进入chapter14根目录,然后输入命令:
ant -file build3.xml run
就会运行BusinessService类。BusinessService的main()方法调用test()方法,test()方法依次调用以下方法:
findAllHourlyEmployees():检索数据库中所有的HourlyEmployee对象。 findAllEmployees():检索数据库中所有的Employee对象。 loadCompany():加载一个Company对象。 saveEmployee():保存一个Employee对象。
(1)运行findAllHourlyEmployees()方法,它的代码如下:
tx = session.beginTransaction(); List results=session.find("from HourlyEmployee"); tx.commit(); return results; 在运行Session的find()方法时,Hibernate执行以下select语句: select * from HOURLY_EMPLOYEES he inner join EMPLOYEES e on he.EMPLOYEE_ID=e.ID; select * from COMPANIES where ID=1;
Hibernate通过HE表与EMPLOYEES表的内连接获得HourlyEmployee对象的所有属性值,此外,在加载HourlyEmployee对象时,还会同时加载与它关联的Company对象。
(2)运行findAllEmployees()方法,它的代码如下:
tx = session.beginTransaction(); List results=session.find("from Employee"); tx.commit(); return results; 在运行Session的find()方法时,Hibernate执行以下select语句: select * from EMPLOYEES e left outer join HOURLY_EMPLOYEES he on e.ID=he.EMPLOYEE_ID left outer join SALARIED_EMPLOYEES se on e.ID=se.EMPLOYEE_ID; select * from COMPANIES where ID=1;
tx = session.beginTransaction(); Company company=(Company)session.load(Company.class,new Long(id)); Hibernate.initialize(company.getEmployees()); tx.commit();
这种映射方式支持多态关联。如果在Company.hbm.xml文件中对employees集合设置了立即检索策略,那么Session的load()方法加载的Company对象的employees集合中包含所有关联的Employee对象。由于本书提供的Company.hbm.xml文件对employees集合设置了延迟检索策略,因此以上程序代码还通过Hibernate类的静态initialize()方法来显式初始化employees集合。
(4)运行saveEmployee(Employee employee)方法,它的代码如下:
tx = session.beginTransaction(); session.save(employee); tx.commit();
在test()方法中,创建了一个HourlyEmployee实例,然后调用saveEmployee()方法保存这个实例:
Employee employee=new HourlyEmployee("Mary",300,company); saveEmployee(employee);
Session的save()方法能判断employee变量实际引用的实例的类型,如果employee变量引用HourlyEmployee实例,就执行如下insert语句:
insert into EMPLOYEES (ID,NAME, COMPANY_ID) values (5, 'Mary', 1); insert into HOURLY_EMPLOYEES (EMPLOYEE_ID ,RATE) values (5, 300);
可见,每保存一个HourlyEmployee对象,需要分别向EMPLOYEES表和HE表插入一条记录,EMPLOYEES表的记录和HE表的记录共享同一个主键。
(出处:http://www.cncms.com)
- ››Hibernate高级应用:性能优化策略
- ››hibernate 多对多关系详解(包括中间表,一对多字表...
- ››Hibernate实现mysql数据库limit查询方法
- ››精通Photoshop之通道详解
- ››Hibernate 之父:是时候升级到Java EE 6了
- ››Hibernate查询
- ››Hibernate和iBATIS比较(摘自网络)
- ››Hibernate使用Projections进行聚合操作
- ››hibernate中java.util.Date类型映射
- ››hibernate中update与saveOrUpdate的区别
- ››精通 Grails: 使用 Grails 进行单元测试(单元测试...
- ››Hibernate各种映射关系总结
更多精彩
赞助商链接