Hibernate读书笔记-----Hibernate的关联映射之1-N关联映射(二)

2014-11-24 08:34:34 · 作者: · 浏览: 5
就在于:从Department到Employee的关联并没有被当中为Department对象状态的一部分(程序是通过吧Employee实体添加到Department实体的集合属性中,而Employee实体并不知道她所关联的Department实体),因而Hibernate无法在执行insert语句为该外键指定值。
为了解决这个问题,程序必须在持久化Employee实体之前,让Employee实体能够知道它所关联的Department实体,也就是通过employee.setDepartment(department);方法建立关联关系,但是这个时候就已经变成了1-N的双向关联。所以,尽量少用1-N的单向关联,而改用1-N的双向关联。

1.2基于有连接表的单向1-N关联
对于有连接表的1-N关联映射,映射文件不再使用元素映射关联实体,而是使用元素,但是为了保证当前实体是1的一端,我们需要增加一个属性:unique="true"。
所以Department.hbm.xml配置文件如下:
[html]















Employee.hbm.xml配置文件保持不变
如果我们依然通过使用操作方法:保存一个Department、两个Employee,这个时候,系统应该是产生5条sql语句。其中两条是用于向连接表中插入记录,从而建立Department和Employee之间的关联关系。

2、双向1-N关联
对于1-N关联,Hibernate推荐使用双向关联,而且不要让1端控制关联关系,而使用N的一端控制关联关系。
双向的1-N关联,两端都需要增加对关联属性的访问,N的一端增加引用到关联实体的属性,1的一端增加集合属性,集合元素为关联实体。
两个持久化类和上面差不多,只需要在Employee中增加对Department的引用属性即可。
2.1无连接表的双向1-N关联
对于无连接表的双向1-N关联。N的一端需要增加元素来映射关联属性,而1的一端需要使用或者元素来映射关联属性。同时或者元素需要增加子元素映射外键列,并且使用子元素映射关联属性。
在前面已经提到对于1-N关联映射,通常不提倡1的一端控制关联关系,而应该由N的一端来控制关联关系。此时我们可以再元素中指定inverse="true",用于指定1的一端不控制关联关系
Department映射文件:Department.hbm.xml
[html]














Employee映射文件:Employee.hbm.xml
[html] view plaincopyprint









下面的程序段用于保存一个Department对象和两个Employee对象
[java]
static void add(){
Session session = HibernateUtil.getSession();
Transaction tx = session.beginTransaction();

Department department = new Department();
department.setName("国防部");

//建立两个对象
Employee employee1 = new Employee();
employee1.setName("chentmt1");
employee1.setDepartment(department); //建立两个对象的关联关系

Employee employee2 = new Employee();
employee2.setName("chentmt2");
employee2.setDepartment(department); //建立两个对象的关联关系

session.save(department); //....1
session.save(employee2);
session.save(employee1);
tx.commit();
session.close();
}

SQL语句:
[sql]
Hibernate: insert into department (departmentName) values ( )

Hibernate: insert into employee (employeeName, departmentID) values ( , )

Hibernate: insert into employee (employeeName, departmentID) values ( , )

通过上面的SQL语句可以看出,Hibernate并不是采用哪种先insert后update的方式来插入employee记录的。而是通过一条insert SQL语句来执行的。为什么?因为程序持久化Employee实体之前,Employee已经知道它所关联Department实体(employee2.setDepartment(department);)。 所以为了保证比较好的性能,需要注意以下两个问题:
1、应该先持久化主表对象:Department。因为我们希望程序在持久化从表:Employee对象时,Hibernate可以为他的外键属性值分配值。
2、先设置两个持久化类(Department和Employee)的关系,再保存持久化从表对象(Employee)。如果顺序反过来,程序持久化Employee对象时,该对象还没有关联实体,所以Hibernate不能为对应记录的外键列指定值,等到设置关联关系时,Hibernate只能再次使用update语句来修改了。

2.2有连接表的双向1-N关联
有连接表的双向1-N关联。1的一端使用集合元素映射,然后在集合元素中增加子元素,该子元素映射到关联类。为保证该实体是1的一端,需要增加unique="true"属性。N的一端则使用元素来强制使用连接表。
在N的一端使用元素强制使用连接表,因此将使用子元素来映射连接表中外