inverse 的作用:询问是否放弃维护关系,默认是false ,即不放弃维护关系,即要维护关系。下面借助前面的“一对多”实例来详谈“维护关系问题”。
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 等有序集合中进行配置。