`
cfeers
  • 浏览: 134922 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

hibernate入门(十一):级联操作inversin属性

阅读更多

九、关联关系中的高级应用

1.级联操作

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

Set<Employee> emps = new HashSet<Employee>();

emps.add(emp1);

emps.add(emp2);

depart.setEmps(emps);
去掉这段注释,并把s.save(emp1); s.save(emp2);注释掉,然后运行发现出错。原因是:当我们保存Department depart对象时,发现它所关联到的两个Employee  emp对象并未保存,而这种要依赖别的对象的操作即是级联操作,级联操作主要体现在关联关系中,且是可配置的,只是默认的级联操作是被设为”none”,而如果我们希望进行级联操作,只需要在<set>配置中增加cascade属性,比如我们现在Department.hbm.xml <set>元素下增加cascade="save-update"属性后,再来执行会发现正常,原因是Hibernate进行了级联操作,相当Hibernate帮我们写了注释掉的“s.save(emp1); s.save(emp2)”这两句内容。下面列表说明级联操作的可选值。

 

cascade属性值

功能作用描述

none

在保存、修改对象时,不对与之关联的对象进行任何操作,它作为cascade默认值。

save-update

当保存或修改对象时,级联保存所有与之关联的临时对象,级联更新所有与之关联的脱管(游离)对象。

delete

当删除时,级联删除所有与之关联的对象

all

包括save-updatedelete两种行为

delete-orphan

删除所有和本对象解除关联关系的对象,主要表现在“一对多”中。

all-delete-orphan

包括alldelete-orphan的行为

说明:(1cascade可以在<set><list><bag><map>中进行配置,即在“多对一”、“一对多”、“多对多”、“一对一这些关联关系中,“级联”都是可配的在一般的对象中不能配置。(2)可以为其配置多个属性值,中间用逗号分隔。如cascade=”save-update,delete”.(3)一般只在“一对一  一对多”配置级联,而不会在“多对一 多对多”中配置级联,但在配置时最好的方法是根据实际情况进行配置。现举例说明:比如在“部门和员工”之间,如果我们希望部门取消时,属于该部门的员工并不会被取消,而是分到的别的部门,我们就不应为cascade配置“delete”值。

2.inverse属性

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

Java代码 复制代码
  1. static void add() {   
  2.         Session s = null;   
  3.         Transaction tx = null;   
  4.         try {   
  5.             Department depart = new Department();   
  6.             depart.setName("departName");   
  7.   
  8.             Employee emp1 = new Employee();   
  9.             emp1.setName("empName1");   
  10.             emp1.setDepart(depart);//员工维护它们之间的关系   
  11.                
  12.             Employee emp2 = new Employee();   
  13.             emp2.setName("empName2");   
  14.             emp2.setDepart(depart);   
  15.   
  16.             Set<Employee> emps = new HashSet<Employee>();   
  17.             emps.add(emp1);   
  18.             emps.add(emp2); //员工维护它们之间的关系   
  19.             depart.setEmps(emps); //部门维护它们之间的关系   
  20.   
  21.             s = HibernateUtil.getSession();   
  22.             tx = s.beginTransaction();   
  23.   
  24.             s.save(emp2);    
  25.             s.save(emp1);   
  26.             s.save(depart);   
  27.             //以上的代码的书写顺序分两种情况讨论    
  28.             tx.commit();   
  29.         } finally {   
  30.             if (s != null)   
  31.                 s.close();   
  32.         }   
  33.     }  
static void add() {
		Session s = null;
		Transaction tx = null;
		try {
			Department depart = new Department();
			depart.setName("departName");

			Employee emp1 = new Employee();
			emp1.setName("empName1");
			emp1.setDepart(depart);//员工维护它们之间的关系
			
			Employee emp2 = new Employee();
			emp2.setName("empName2");
			emp2.setDepart(depart);

			Set<Employee> emps = new HashSet<Employee>();
			emps.add(emp1);
			emps.add(emp2); //员工维护它们之间的关系
			depart.setEmps(emps); //部门维护它们之间的关系

			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文件,在<set>元素下增加“inverse="true"”属性后,再来执行“OneToManyTest”,可以明显感受到“一”放弃了维护关系。

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

分享到:
评论
2 楼 RobustTm 2011-03-01  
我的这种做法也可以添加A和B
但是换成更新就有问题
1 楼 RobustTm 2011-03-01  
这位仁兄可以提供一对多双向关联完整的代码不?
我碰到了问题,采用你里面的做法也不行啊。
我大致要做的流程是:
更新一个表的信息 A表,B表中有个字段是A的主键,A与B外键关联
页面中有A表和B表的信息
A表中的id(主键)确定,其他信息需要更新,主键不是自增的,是String类型,设置的
而B表是添加插入的操作。

A.java
public class A{
    private String a_id;
    private String title;
    private String content;
    Set<B> b;
}

B.java
public class B{
    private String b_id;
    private A a;
    private String content;
}
xml
B
<many-to-one name="a" column="a_id" class="com.bean.A"/>

A
<set name="b" lazy="true" table="B"
order-by="id desc" inverse="true" cascade="save-update">
<key column="a_id" />
<one-to-many class="com.bean.B" />
</set>

具体的更新大致是
A a = aDAOImpl.getA(a_id);
a.setTitle(title);
a.setContent(content);

B b = new B();
b.setId(b_id);
b.setA(a);
b.setContent(content);

aDAOImpl.update(a);
bDAOImpl.add(b);

更新不成功,操作相当慢,最后数据库连接都断了
忘仁兄指导

相关推荐

Global site tag (gtag.js) - Google Analytics