分享
 
 
 

精通Hibernate映射继承关系之二

王朝other·作者佚名  2008-05-31
窄屏简体版  字體: |||超大  

把每个具体类映射到一张表是最简单的映射方式。如图14-2所示,在关系数据模型中只需定义COMPANIES、HOURLY_EMPLOYEES和SALARIED_EMPLOYEES表。为了叙述的方便,下文把HOURLY_EMPLOYEES表简称为HE表,把SALARIED_EMPLOYEES表简称为SE表。

HourlyEmployee类和HE表对应,HourlyEmployee类本身的rate属性,以及从Employee类中继承的id属性和name属性,在HE表中都有对应的字段。此外,HourlyEmployee类继承了Employee类与Company类的关联关系,与此对应,在HE表中定义了参照COMPANIES表的COMPANY_ID外键。

SalariedEmployee类和SE表对应,SalariedEmployee类本身的salary属性,以及从Employee类中继承的id属性和name属性,在SE表中都有对应的字段。此外,SalariedEmployee类继承了Employee类与Company类的关联关系,与此对应,在SE表中定义了参照COMPANIES表的COMPANY_ID外键。

Company类、HourlyEmployee类和SalariedEmployee类都有相应的映射文件,而Employee类没有相应的映射文件。图14-3显示了持久化类、映射文件和数据库表之间的对应关系。

图14-2 每个具体类对应一个表

图14-3 持久化类、映射文件和数据库表之间的对应关系

如果Employee类不是抽象类,即Employee类本身也能被实例化,那么还需要为Employee类创建对应的EMPLOYEES表,此时HE表和SE表的结构仍然和图14-2中所示的一样。这意味着在EMPLOYEES表、HE表和SE表中都定义了相同的NAME字段以及参照COMPANIES表的外键COMPANY_ID。另外,还需为Employee类创建单独的Employee.hbm.xml文件。

14.1.1 创建映射文件

从Company类到Employee类是多态关联,但是由于关系数据模型没有描述Employee类和它的两个子类的继承关系,因此无法映射Company类的employees集合。例程14-1是Company.hbm.xml文件的代码,该文件仅仅映射了Company类的id和name属性。

例程14-1 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" />

</class>

</hibernate-mapping>

HourlyEmployee.hbm.xml文件用于把HourlyEmployee类映射到HE表,在这个映射文件中,除了需要映射HourlyEmployee类本身的rate属性,还需要映射从Employee类中继承的name属性,此外还要映射从Employee类中继承的与Company类的关联关系。例程14-2是HourlyEmployee.hbm.xml文件的代码。

例程14-2 HourlyEmployee.hbm.xml

<hibernate-mapping >

<class name="mypack.HourlyEmployee" table="HOURLY_EMPLOYEES">

<id name="id" type="long" column="ID">

<generator class="increment"/>

</id>

<property name="name" type="string" column="NAME" />

<property name="rate" column="RATE" type="double" />

<many-to-one

name="company"

column="COMPANY_ID"

class="mypack.Company"

/>

</class>

</hibernate-mapping>

SalariedEmployee.hbm.xml文件用于把SalariedEmployee类映射到SE表,在这个映射文件中,除了需要映射SalariedEmployee类本身的salary属性,还需要映射从Employee类中继承的name属性,此外还要映射从Employee类中继承的与Company类的关联关系。例程14-3是SalariedEmployee.hbm.xml文件的代码。

例程14-3 SalariedEmployee.hbm.xml

<hibernate-mapping >

<class name="mypack.SalariedEmployee" 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" />

<many-to-one

name="company"

column="COMPANY_ID"

class="mypack.Company"

/>

</class>

</hibernate-mapping>

由于Employee类没有相应的映射文件,因此在初始化Hibernate时,只需向Configuration对象中加入Company类、HourlyEmployee类和SalariedEmployee类:

Configuration config = new Configuration();

config.addClass(Company.class)

.addClass(HourlyEmployee.class)

.addClass(SalariedEmployee.class);

14.1.2 操纵持久化对象

这种映射方式不支持多态查询,在本书第11章的11.1.6节(多态查询)介绍了多态查询的概念。对于以下查询语句:

List employees=session.find("from Employee");

如果Employee类是抽象类,那么Hibernate会抛出异常。如果Employee类是具体类,那么Hibernate仅仅查询EMPLOYEES表,检索出Employee类本身的实例,但不会检索出它的两个子类的实例。本节的范例程序位于配套光盘的sourcecode\chapter14\14.1目录下,运行该程序前,需要在SAMPLEDB数据库中手工创建COMPANIES表、HE表和SE表,然后加入测试数据,相关的SQL脚本文件为\14.1\schema/sampledb.sql。

在chapter14目录下有四个ANT的工程文件,分别为build1.xml、build2.xml、build3.xml和build4.xml,它们的区别在于文件开头设置的路径不一样,例如在build1.xml文件中设置了以下路径:

<property name="source.root" value="14.1/src"/>

<property name="class.root" value="14.1/classes"/>

<property name="lib.dir" value="lib"/>

<property name="schema.dir" value="14.1/schema"/>

在DOS命令行下进入chapter14根目录,然后输入命令:

ant -file build1.xml run

就会运行BusinessService类。ANT命令的-file选项用于显式指定工程文件。BusinessService类用于演示操纵Employee类的对象的方法,例程14-4是它的源程序。

例程14-4 BusinessService.java

public class BusinessService{

public static SessionFactory sessionFactory;

static{

try{

Configuration config = new Configuration();

config.addClass(Company.class)

.addClass(HourlyEmployee.class)

.addClass(SalariedEmployee.class);

sessionFactory = config.buildSessionFactory();

}catch(Exception e){e.printStackTrace();}

}

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(employees.iterator());

Company company=loadCompany(1);

printAllEmployees(company.getEmployees().iterator());

Employee employee=new HourlyEmployee("Mary",300,company);

saveEmployee(employee);

}

private void printAllEmployees(Iterator it){

while(it.hasNext()){

Employee e=(Employee)it.next();

if(e instanceof HourlyEmployee){

System.out.println(((HourlyEmployee)e).getRate());

}else

System.out.println(((SalariedEmployee)e).getSalary());

}

}

public static void main(String args[]) throws Exception {

new BusinessService().test();

sessionFactory.close();

}

}

BusinessService的main()方法调用test()方法,test()方法依次调用以下方法。

findAllEmployees():检索数据库中所有的Employee对象。

loadCompany():加载一个Company对象。

saveEmployee():保存一个Employee对象。

(1)运行findAllEmployees()方法,它的代码如下:

List results=new ArrayList();

tx = session.beginTransaction();

List hourlyEmployees=session.find("from HourlyEmployee");

results.addAll(hourlyEmployees);

List salariedEmployees=session.find("from SalariedEmployee");

results.addAll(salariedEmployees);

tx.commit();

return results;

为了检索所有的Employee对象,必须分别检索所有的HourlyEmployee实例和SalariedEmployee实例,然后把它们合并到同一个集合中。在运行Session的第一个find()方法时,Hibernate执行以下select语句:

select * from HOURLY_EMPLOYEES;

select * from COMPANIES where ID=1;

从HourlyEmployee类到Company类不是多态关联,在加载HourlyEmployee对象时,会同时加载与它关联的Company对象。

在运行Session的第二个find()方法时,Hibernate执行以下select语句:

select * from SALARIED_EMPLOYEES;

从SalariedEmployee类到Company类不是多态关联,在加载SalariedEmployee对象时,会同时加载与它关联的Company对象。在本书提供的测试数据中,所有HourlyEmployee实例和SalariedEmployee实例都与OID为1的Company对象关联,由于该Company对象已经被加载到内存中,所以Hibernate不再需要执行检索该对象的select语句。

(2)运行loadCompany()方法,它的代码如下:

tx = session.beginTransaction();

Company company=(Company)session.load(Company.class,new Long(id));

List hourlyEmployees=session.find("from HourlyEmployee h where h.company.id="+id);

company.getEmployees().addAll(hourlyEmployees);

List salariedEmployees=session.find("from SalariedEmployee s where s.company.id="+id);

company.getEmployees().addAll(salariedEmployees);

tx.commit();

return company;

由于这种映射方式不支持多态关联,因此由Session的load()方法加载的Company对象的employees集合中不包含任何Employee对象。BusinessService类必须负责从数据库中检索出所有与Company对象关联的HourlyEmployee对象以及SalariedEmployee对象,然后把它们加入到employees集合中。

(3)运行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实例,就向HE表插入一条记录,执行如下insert语句:

insert into HOURLY_EMPLOYEES(ID,NAME,RATE,CUSTOMER_ID)

values(3, 'Mary',300,1);

如果employee变量引用SalariedEmployee实例,就向SE表插入一条记录。

(出处:http://www.knowsky.com)

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有