<hibernatemapping >
<class name=mypackSalariedEmployee table=SALARIED_EMPLOYEES>
<id name=id type=long column=ID>
<generator class=increment/>
</id>
<property name=name type=string column=NAME />
<property name=salary column=SALARY type=double />
<manytoone
name=company
column=COMPANY_ID
class=mypackCompany
/>
</class>
</hibernatemapping>
由于Employee类没有相应的映射文件因此在初始化Hibernate时只需向Configuration对象中加入Company类HourlyEmployee类和SalariedEmployee类
Configuration config = new Configuration();
configaddClass(Companyclass)
addClass(HourlyEmployeeclass)
addClass(SalariedEmployeeclass);
操纵持久化对象
这种映射方式不支持多态查询在本书第章的节(多态查询)介绍了多态查询的概念对于以下查询语句
List employees=sessionfind(from Employee);
如果Employee类是抽象类那么Hibernate会抛出异常如果Employee类是具体类那么Hibernate仅仅查询EMPLOYEES表检索出Employee类本身的实例但不会检索出它的两个子类的实例本节的范例程序位于配套光盘的sourcecode\chapter\目录下运行该程序前需要在SAMPLEDB数据库中手工创建COMPANIES表HE表和SE表然后加入测试数据相关的SQL脚本文件为\\schema/sampledbsql
在chapter目录下有四个ANT的工程文件分别为buildxmlbuildxmlbuildxml和buildxml它们的区别在于文件开头设置的路径不一样例如在buildxml文件中设置了以下路径
<property name=sourceroot value=/src/>
<property name=classroot value=/classes/>
<property name=libdir value=lib/>
<property name=schemadir value=/schema/>
在DOS命令行下进入chapter根目录然后输入命令
antfilebuildxmlrun
就会运行BusinessService类ANT命令的file选项用于显式指定工程文件BusinessService类用于演示操纵Employee类的对象的方法例程是它的源程序
例程 BusinessServicejava
public class BusinessService{
public static SessionFactory sessionFactory;
static{
try{
Configuration config = new Configuration();
configaddClass(Companyclass)
addClass(HourlyEmployeeclass)
addClass(SalariedEmployeeclass);
sessionFactory = configbuildSessionFactory();
}catch(Exception e){eprintStackTrace();}
}
public void saveEmployee(Employee employee) throws Exception{……}
public List findAllEmployees() throws Exception{……}
public Company loadCompany(long id) throws Exception{……}
public void test() throws Exception{
List employees=findAllEmployees();
printAllEmployees(erator());
Company company=loadCompany();
printAllEmployees(companygetEmployees(erator());
Employee employee=new HourlyEmployee(Marycompany);
saveEmployee(employee);
}
private void printAllEmployees(Iterator it){
while(ithasNext()){
Employee e=(Employee)itnext();
if(e instanceof HourlyEmployee){
Systemoutprintln(((HourlyEmployee)e)getRate());
}else
Systemoutprintln(((SalariedEmployee)e)getSalary());
}
}
public static void main(String args[]) throws Exception {
new BusinessService()test();
sessionFactoryclose();
}
}
BusinessService的main()方法调用test()方法test()方法依次调用以下方法
findAllEmployees()检索数据库中所有的Employee对象
loadCompany()加载一个Company对象
saveEmployee()保存一个Employee对象
()运行findAllEmployees()方法它的代码如下
List results=new ArrayList();
tx = sessionbeginTransaction();
List hourlyEmployees=sessionfind(from HourlyEmployee);
resultsaddAll(hourlyEmployees);
List salariedEmployees=sessionfind(from SalariedEmployee);
resultsaddAll(salariedEmployees);
mit();
return results;
为了检索所有的Employee对象必须分别检索所有的HourlyEmployee实例和SalariedEmployee实例然后把它们合并到同一个集合中在运行Session的第一个find()方法时Hibernate执行以下select语句
select * from HOURLY_EMPLOYEES;
select * from COMPANIES where ID=;
从HourlyEmployee类到Company类不是多态关联在加载HourlyEmployee对象时会同时加载与它关联的Company对象
在运行Session的第二个find()方法时Hibernate执行以下select语句
select * from SALARIED_EMPLOYEES;
从SalariedEmployee类到Company类不是多态关联在加载SalariedEmployee对象时会同时加载与它关联的Company对象在本书提供的测试数据中所有HourlyEmployee实例和SalariedEmployee实例都与OID为的Company对象关联由于该Company对象已经被加载到内存中所以Hibernate不再需要执行检索该对象的select语句
()运行loadCompany()方法它的代码如下
tx = sessionbeginTransaction();
Company company=(Company)sessionload(Companyclassnew Long(id));
List hourlyEmployees=sessionfind(from HourlyEmployee h where panyid=+id);
companygetEmployees()addAll(hourlyEmployees);
List salariedEmployees=sessionfind(from SalariedEmployee s where panyid=+id);
companygetEmployees()addAll(salariedEmployees);
mit();
return company;
由于这种映射方式不支持多态关联因此由Session的load()方法加载的Company对象的employees集合中不包含任何Employee对象BusinessService类必须负责从数据库中检索出所有与Company对象关联的HourlyEmployee对象以及SalariedEmployee对象然后把它们加入到employees集合中
()运行saveEmployee(Employee employee)方法它的代码如下
tx = sessionbeginTransaction();
sessionsave(employee);
mit();
在test()方法中创建了一个HourlyEmployee实例然后调用saveEmployee()方法保存这个实例
Employee employee=new HourlyEmployee(Marycompany);
saveEmployee(employee);
Session的save()方法能判断employee变量实际引用的实例的类型如果employee变量引用HourlyEmployee实例就向HE表插入一条记录执行如下insert语句
insert into HOURLY_EMPLOYEES(IDNAMERATECUSTOMER_ID)
values( Mary);
如果employee变量引用SalariedEmployee实例就向SE表插入一条记录