Hibernate快速入门教程(5)

2018-11-17 21:45

[键入文字]

的集合对象也是一样的道理。

九、关联关系中的高级应用 1.级联操作:

在前面的一对多操作中已经有所体现,现在回到前面的一对多操作中,进行一些修改,修改内容如下:

Set emps = new HashSet(); emps.add(emp1); emps.add(emp2);

depart.setEmps(emps); 去掉这段注释,并把“s.save(emp1); s.save(emp2);”注释掉,然后运行发现出错。原因是:当我们保存Department depart对象时,发现它所关联到的两个Employee emp对象并未保存,而这种要依赖别的对象的操作即是级联操作,级联操作主要体现在关联关系中,且是可配置的,只是默认的级联操作是被设为”none”,而如果我们希望进行级联操作,只需要在配置中增加cascade属性,比如我们现在Department.hbm.xml 的元素下增加

cascade=\属性后,再来执行会发现正常,原因是Hibernate进行了级联操作,相当Hibernate帮我们写了注释掉的“s.save(emp1); s.save(emp2)”这两句内容。下面列表说明级联操作的可选值。 cascade属性值 功能作用描述 none 在保存、修改对象时,不对与之关联的对象进行任何操作,它作为cascade默认值。 save-update 当保存或修改对象时,级联保存所有与之关联的临时对象,级联更新所有与之关联的脱管(游离)对象。 delete 当删除时,级联删除所有与之关联的对象 all 包括save-update和delete两种行为 delete-orphan 删除所有和本对象解除关联关系的对象,主要表现在“一对多”中。 all-delete-orphan 包括all和delete-orphan的行为 说明:(1)cascade可以在中进行配置,即在“多对一”、“一对多”、“多对多”、“一对一”

这些关联关系中,“级联”都是可配的在一般的对象中不能配置。

(2)可以为其配置多个属性值,中间用逗号分隔。如cascade=”save-update,delete”.

(3)一般只在“一对一 一对多”配置级联,而不会在“多对一 多对多”中配置级联,但在配置时最好的方法是根据实际情况进行配置。现举例说明:比如在“部门和员工”之间,如果我们希望部门取消时,属于该部门的员工并不会被取消,而是分到的别的部门,我们就不应为cascade配置“delete”值。

2.inverse属性: inverse的作用:询问是否放弃维护关系,默认是false,即不放弃维护关系,即要维护关系。下面借助前面的“一对多”实例来详谈“维护关系问题”。

static void add() {

Session s = null;

Transaction tx = null; try {

Department depart = new Department(); depart.setName(\ Employee emp1 = new Employee(); emp1.setName(\

emp1.setDepart(depart);//员工维护它们之间的关系

Employee emp2 = new Employee(); emp2.setName(\ emp2.setDepart(depart);

Set emps = new HashSet(); emps.add(emp1);

emps.add(emp2); //员工维护它们之间的关系

depart.setEmps(emps); //部门维护它们之间的关系

- 21 - / 42

[键入文字]

}

s = HibernateUtil.getSession(); tx = s.beginTransaction(); s.save(emp2); s.save(emp1); s.save(depart);

//以上的代码的书写顺序分两种情况讨论 tx.commit(); } finally {

if (s != null) s.close(); }

下面借助上面的代码来进行分析:一种情况下是员工维护它们之间的关系。其中的关键代码为已在上面说明

(即emp1.setDepart(depart),emp2.setDepart(depart)):此时,我们再注释掉部门维护关系的代码(即注释掉depart.setEmps(emps);),然后执行;执行后再交换s.save(emp2); s.save(emp1);s.save(depart);的保存顺序,再执行。

第二种情况是,部门维护它们之间的关系,需注释掉员工维护关系,再分保存的顺序讨论。 第三种情况是,共同维护它们之间的关系。 下面再列表说明: 先保存员工,再保存部门 先保存部门,再保存员工 由于是员工维护关系,当我们先由于先保存了部门信息,然后再来保存员工维护关系 保存员工再保存部门时,会自动员工时,便能获知部门信息,所以只进把部门信息更新到员工表中,这行了插入操作,不会有任何更新操作。 时会有两条更新操作。 由于是部门来维护关系,不论怎样的保存顺序,最终都会有两条更新操作。部门维护关系 原因是我们要更新的是员工表,当我们最终保存好部门和员工后,都会再把部门信息更新到员工表中。 共同维护关系 4条更新操作,结合上面分析 2条更新操作,结合上面分析。 分析了上面的维护关系情况,下面再来讨论由谁来维护关系:举例,在“一对多”中,如果让“一”来维护关系,相对就低效,如果让“多”来维护关系,则会在效率上有很大的提高。再据此举个生活中的例子,一个老师会有多个学生,如果让老师来维护关系,让老师来记住学生,这将会很难,但如果我们让学生来维护关系,即让每个学生来记住老师,这样将会使效率上有很大的提高,所以通常在关联关系中,我们总是会让“多”这方来维护关系,而让“一”这方放弃维护关系。因此我们需要在“一”的一方配置“inverse”属性,让它来放弃维护关系。为什么要一方放弃维护关系?在上面的例子中,我们在讨论让双方共同维护关系时,会发现有重复的操作,这就是为什么要提出放弃维护关系的原因,在前面的“多对多”实例中,如果让双方都来维护关系将会报错,原因很简单:“多对多”采取的中间表关联,而双方维护关系,将会试图在中间表插入重复的记录,当然是不可行的,至于在“一对多”等关联关系中可以双方维护关系是因为它采取的是更新外键操作。 总结:在“一对多”中,维护关系表现为更新外键,而“多对多”,维护关系表现为在“中间表”中增减记录。 下面我们修改Department.hbm.xml文件,在元素下增加“inverse=\”属性后,再来执行“OneToManyTest”,可以明显感受到“一”放弃了维护关系。

注意:inverse只出现在集合类型的标签中,但不能在list等有序集合中进行配置。 3.继承关系:

在前面的部门员工实例中,我们设定的员工只是普通的员工,现在假如有Sale和Skill两类员工,它们作为Employee的子类。如何实现这些子类的映射?为了方便以后的操作说明和不影响以前的操作,我们把前面用到的员工部门类及相关实体配置文件,主配置文件等拷贝到一个新的项目theExtend下进行操作。

(1)共享一张表:

意思是我们把子类的当作父类来处理共同映射成一张表。

>>步骤一,创建Employee的子类:Sale和Skill。内容如下:

package com.asm.hibernate.domain;

- 22 - / 42

[键入文字]

public class Sale extends Employee { private String signSale; ...省略getXXX setXXX() }

package com.asm.hibernate.domain; public class Skill extends Employee{ private String signSkill; ...省略getXXX setXXX() }

>>步骤二、修改Employee.hbm.xml配置文件:

配置文件说明: 理解元素:它作为class的子元素,但是它却和class非常相似,name同样是指所关联

到的“类”,下面的也与class下的一样。我们注意到它和class均增加了一个新属性discriminator-value,它的作用就是配置这些类的“鉴别类型”。而discriminator-value 的配置主要参照的是,它通常称为鉴别类型,即是说鉴别属于什么类型,因为在涉及到继承关系的操作时,总会涉及到父子类的关系,比如在上面的配置中,我们设定了sign子段来标识类型,执行后会再对此作说明。 注意:要写在后面元素的前面,因为它的dtd文件是这样规定得。

>>步骤三、修改主配置文件,由于是拷贝的前面的文件,所以需要去掉无关的映射文件,否则会提示找不到这此

映射文件。

>>步骤四、编写测试类:

package com.asm.hibernate.test; public class ManyToOneTest {

public static void main(String[] args) { add();

Employee emp=query(2);

System.out.println(\ }

static Employee query(int empId) { Session s = null; try {

s = HibernateUtil.getSession();

Employee emp = (Employee) s.get(Employee.class, empId);

System.out.println(\ return emp;

- 23 - / 42

[键入文字]

}

} finally {

if (s != null) s.close(); } }

static void add() { Session s = null;

Transaction tx = null; try {

Department depart = new Department(); depart.setName(\ Employee emp = new Employee(); emp.setName(\ emp.setDepart(depart); Sale emp2 = new Sale();

emp2.setName(\ emp2.setSignSale(\ emp2.setDepart(depart); Skill emp3 = new Skill();

emp3.setName(\ emp3.setSignSkill(\ emp3.setDepart(depart);

s = HibernateUtil.getSession(); tx = s.beginTransaction(); s.save(emp); s.save(emp2); s.save(emp3); s.save(depart); tx.commit(); } finally {

if (s != null) s.close(); } }

说明:没的什么可多言的,只是要注意在查询时能返回其子类型。 下面来看执行后employee表的内容:

+----+------+---------------+-----------+----------+-----------+ | id | sign | name | depart_id | signSale | signSkill | +----+------+---------------+-----------+----------+-----------+ | 1 | 0 | empName | 1 | NULL | NULL | | 2 | 1 | saleEmployee | 1 | saleName | NULL | | 3 | 2 | skillEmployee | 1 | NULL | skillName | +----+------+---------------+-----------+----------+-----------+

先来看sign这列:由于sign是鉴别类型设定的字段,且分别在前面为Employee、Sale、Skill分别配置了“0、1、2”所以它们会在sign体现出来。其实

再来看“signSale、signSkill”字段:它们本身是专为特定的类的属性配置的字段(比如在第一个元素下的property子元素就配置了Sale类的signSale属性):所以它们只适合特定的类,而不适的类将会以null来填

- 24 - / 42

[键入文字]

充,这也就是如果采取“共享一张表”的最大缺点,它限制了我们不能在子类属性所映射的字段上设定“非空”。由于查询只涉及到一张表,所以效率较高。

(2)每个子类一张附表:

意思是每个类均会有一张表,但是它不是完整的表,因为它的一些字段还在父类的表中。即是说:公共字段放在父表中,子类子类分别放在子类所映射的表中,它们之间采取主外键关联。这样解决了上面的“不能设定为空”的缺限。接上面只需修改Employee.hbm.xml配置文件,修改后的内容如下:

配置文件说明:当每个子类都会有一张表,在class子元素下设定了元素,它的意思就是专门

指定为子类映射成一张表,特别要说明的是我们为每个子类都配置了元素,它的作用就是作为外键关联employee表,它的值也是参照class元素的id来生成。执行后的表内容如下: skill表 sale表 +----------+-----------+ +---------+----------+ | skill_id | signSkill | | sale_id | signSale | +----------+-----------+ +---------+----------+ | 3 | skillName | | 2 | saleName | +----------+-----------+ +---------+----------+ employee表 +----+---------------+-----------+ | id | name | depart_id | +----+---------------+-----------+ | 1 | empName | 1 | | 2 | saleEmployee | 1 | | 3 | skillEmployee | 1 | +----+---------------+-----------+ 执行后请留意hibernate产生的sql语句。

(3)联合使用表:

意思是同时使用(1)(2)的形式,主要目的是为了能使用鉴别类型,但同时也能“设定为非空”。同样只需要修改配置文件,修改后的内容如下:

- 25 - / 42


Hibernate快速入门教程(5).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:刑法学实验课教学方法研究

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: