又从头学习了一遍hibernate的映射关系,每一次都会有新的收获,总是感觉自己还是不会hibernate。单从配置上说:知其然不知其所以然,马上就要找工作的人了,很是为自己担心呀!!
众所周知,hibernate是一个杰出的O/R Mapping(Object-Relationl Mapping)框架,单从英文字面意思来解释:对象关系映射。在面向对象编程的过程中,我们往往先抽象出系统中涉及的实体对象,然后根据对象建立数据表,无疑后面对于数据库的操作是面向过程的。面向对象是简洁的,面向过程(操作数据库,写sql语句)是复杂的。Hibernate恰恰屏蔽了数据库操作这层,用户只需用面向对象的直观意识来操作数据库这更像一个facade模式,提供了对外的接口,用户只需调用接口无需知道具体实现。比如说我想获得某部门所有成员的信息,用hibernate操作一句话就搞定了session.load(Department.class, n),他的成本仅仅是从数据库load出所需的部门对象。这种方式操作数据库才是面向对象的方式,现实世界中也是这样,我想获取这个部门的所有成员,只需要知道这个部门的详细信息,因为他的成员肯定包括在详细信息中。
但是关联关系的作用是什么呢?关联关系就是hibernate处理对象之间所参照的准则。如果你掌握好了这种规则那么hibernate会更高效的为你工作。举一个例子:
假设我们实现一个从Parent到Children的映射:
<set name="children">
<key column="pid">
<one-to-many class="Child">
</set>
当我们试图保存一个Child对象时:
Parent p = session.load(Parent.class, n);
Child c = new Child();
c...
session.save(c);
p.getChildren().add(c);
...
这样我们会得到两条sql语句一条是保存child的语句,另一条是为两者建立关系的sql语句,相当于hibernate执行了两次数据库。
让我们看一个更好的方案:
我们在child方添加配置:
<many-to-one column="parent" nou-null="rue" column="pid" />
修改parent的配置,添加inverse="true"属性,他的意思是将关联关系交给对方管理,在这就是交给了child一方管理。
下面我们再来保存一个child实例:
p.getChildren().add(c);
c.setParent(p);
session.save(c);
这样只会生成一条insert语句,至于建立两者之间关系的那条sql语句在child保存的同时已经由hibernate自动更新了,不要忘了维护child-parent之间关系的责任已经交给child一端了。相比上面的方式,我们可以发现hibernate减少了一次操作数据库的工作,这样的话相当于你的程序提高了一倍的工作效率,当然只是片面的从操作数据库数量上来说。
单向关联关系有如下几种:具体还分为有无连接表的。双向关联关系亦有有无连接表之分。下面我们来看一下如何配置关联关系。
下面这几种是单向关联无连接表的:
下面这几种是单向关联基于连接表的:
下面这几种是双向关联无连接表的:
下面这几种是双向关联基于连接表的: