首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件架构设计 >

hibernate 一对多(one-to-many)双向联系关系

2012-10-14 
hibernate 一对多(one-to-many)双向关联一对多(one-to-many)双向关联实例(Department- Employee)这里的一

hibernate 一对多(one-to-many)双向关联

一对多(one-to-many)双向关联实例(Department- Employee)

这里的一对多双向关联是在域模型(实体对象模型)上的概念,在关系数据库中,只存在外键参照关系,而且总是由"many"方参照"one"方,因为这样才能消除冗余数据,因上关系数据库实际上只支持多对一或一对一的单向关联.在实体(类与类之间)各种各样的关系中,数多对一的的单向关联关系与数据库中的外键参照关系最匹配了.

在我的前一篇文章多对一的基础上进行修改。

1.修改Department实体类:

?控制台打印信息如下:

Hibernate: insert into Department (name) values (?)
Hibernate: insert into Employee (name, depart_id) values (?, ?)
Hibernate: insert into Employee (name, depart_id) values (?, ?)
Hibernate: select department0_.id as id1_0_, department0_.name as name1_0_ from Department department0_ where department0_.id=?
Hibernate: select emps0_.depart_id as depart3_1_, emps0_.id as id1_, emps0_.id as id2_0_, emps0_.name as name2_0_, emps0_.depart_id as depart3_2_0_ from Employee emps0_ where emps0_.depart_id=?

emp size:2

数据库中记录如下所示:

mysql> select * from employee;
+----+-----------------+-----------+
| id | name??????????? | depart_id |
+----+-----------------+-----------+
|? 1 | employee1 name2 |???????? 1 |
|? 2 | employee2 name2 |???????? 1 |
+----+-----------------+-----------+
2 rows in set (0.00 sec)

mysql> select * from department;
+----+-----------------+
| id | name??????????? |
+----+-----------------+
|? 1 | department name |
+----+-----------------+
1 row in set (0.00 sec)

?

虽然对象模型修改了,但数据库关系模型并没有改变。

?

如果把测试程序中注释部分去掉,同时将注释为“建立对象模型”这两句程序注释掉,虽然也能正确运行,但控制台会多打印出两条更新语句,说明数据库多执行了两次更新操作,效率上有影响,如下所示:

Hibernate: insert into Department (name) values (?)
Hibernate: insert into Employee (name, depart_id) values (?, ?)
Hibernate: insert into Employee (name, depart_id) values (?, ?)
Hibernate: update Employee set depart_id=? where id=?
Hibernate: update Employee set depart_id=? where id=?
Hibernate: select department0_.id as id1_0_, department0_.name as name1_0_ from Department department0_ where department0_.id=?
Hibernate: select emps0_.depart_id as depart3_1_, emps0_.id as id1_, emps0_.id as id2_0_, emps0_.name as name2_0_, emps0_.depart_id as depart3_2_0_ from Employee emps0_ where emps0_.depart_id=?
emp size:2

?

4.懒加载分析:

(1)如果将程序中标记为1的程序注释掉,控制台打印信息如下:

Hibernate: select department0_.id as id0_0_, department0_.name as name0_0_ from Department department0_ where department0_.id=?

此时只是将Department对象查询出来了,而对应的Employee并没有进行查询。

(2)如果将程序中标记为1的程序注释掉,同时将标记为2的前面的注释去掉,运行程序,控制台打印信息如下:

Hibernate: select department0_.id as id0_0_, department0_.name as name0_0_ from Department department0_ where department0_.id=?
emps class:class org.hibernate.collection.PersistentSet

此时可以看到其实Hibernate将hashset替换成了它自己写的PersistentSet,所以才能实现懒加载功能。同时可以发现当调用department.getEmps();hibernate只是获取了集合代理对象的引用,它并没有去查询数据库来填充集合对象。你还可以进一步测试来验证这个问题。如果你将程序中标记为1的程序注释掉,同时去掉标记为3的语句前面的注释,你会发现程序能正常运行,但如果去掉标记为4的语句前面的注释,运行程序,则会抛出如下异常:

?org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.reiyen.hibernate.domain.Department.emps, no session or session was closed

(3)当进行department对象查询时,从department的表结构中也不能判断这个Department对象是否有对应的Employee,那为什么它不像一对一查询时,也一次性把相关联的对象查询出来呢??这是因为如果将关联的对象查询出来的话,因为数据较多,它会严重影响效率,而不像一对一时,反正从对象只有一个,一次性查询出来影响也不是太大,所以hibernate就假定你有相对应的Employee,直接创建了一个集合代理对象的返回给你(把对象引用先给你),等你需要数据的时候再去查询数据库,以提高效率!

?

热点排行