在不久前,我们简单的认识了Mybatis这个优秀的持久层框架,现在我们再来简单认识下另一个优秀的orm框架:hibernate。再这里我们不将两者做详细的对比,以后再将两者做一个全面的对比,突出各自的优势。
现在我们来简单认识下这个orm框架:
1.它是什么:
在总结mybatis的时候,那时候我们提到了现在项目的主流架构为4层架构的mvc模式,同mybatis一样,hibernate框架总体处于项目的第三层持久层,用于数据的持久化,它是对JDBC的轻量级封装,如果说mybatis半自动化的orm框架的话,那么hibernate就是全自动的orm框架,因为它根本不需要自己去手动的去写sql语句.
2.它是如何实现的:
(1).由Configuration默认读取scr路径下的hibernate.cfg.xml生成实例,hibernate启动,找到相应的映射文件
(2).而后由Configuration实例得到sessionfactory
(3).sessionfactory得到session(持久化管理器)借口,它提供与持久化相关的操作(增删改查)
(4).关闭session
3.实际的手动实践一下,同mybatis我们从增删改查四个方面来初识下hibernate(所涉及的数据库以及表和mybatis一样)
我记得在做项目的时候一直纠结关联节点的两个属性 inverse和cascade这两个属性,一直迷迷糊糊的,知道这些天看了一些,别人的文章,算是入门了 。大家可以看看这篇文章
:http://developer.51cto.com/art/201104/253932.htm ,http://www.cnblogs.com/amboyna/archive/2008/02/18/1072260.html 我相信大家会有比较深刻体会的。
那我就结合下面的例子,用我自己的话,来谈谈我理解的inverse和cascade这俩属性,在整个过程的作用。
准备工作:
1.数据库:sqlserver2008
表:学生表(sid,bid,sname)
班级表(bid,bname)
课程表(cid,cname)
学生课程表(sid,cid)
2.对应的持久化类,3.对应的映射XML,
(1)增加数据(双向一对多)
班级的映射文件:
<class name="com.cn.entity.Banji" table="banji" schema="dbo" catalog="test">
<id name="bid" type="java.lang.Integer">
<column name="bId" />
<generator class="native" />
</id>
<property name="bname" type="java.lang.String">
<column name="bName" length="50" not-null="true" />
</property>
<set name="stus" cascade="save-update" inverse="true">
<key>
<column name="bId" not-null="true" />
</key>
<one-to-many class="com.cn.entity.Stu" />
</set>
</class>
学生的映射文件:
<class name="com.cn.entity.Stu" table="stu" schema="dbo" catalog="test">
<id name="sid" type="java.lang.Integer">
<column name="sId" />
<generator class="native" />
</id>
<many-to-one name="banji" class="com.cn.entity.Banji" fetch="select">
<column name="bId" />
</many-to-one>
<property name="sname" type="java.lang.String">
<column name="sName" length="50" not-null="true" />
</property>
<set name="courses" table="stu_c" schema="dbo" catalog="test">
<key>
<column name="sId" />
</key>
<many-to-many entity-name="com.cn.entity.Course">
<column name="cId" />
</many-to-many>
</set>
</class>
代码:
@Test
public void insert(){
Transaction tr=session.beginTransaction();
Banji b=new Banji("nihaohao");
Stu stu=new Stu("wll");
stu.setBanji(b);
b.getStus().add(stu);
session.save(b);
tr.commit();
}
上述代码在save时,hibernate持久化处于自由态的b,根据映射文件的描述讲属性和字段一一对应,当涉及到关联属性的时候,首先找一对多节点也就是<set>找属性cascade它的值,如果说它的值没有设定,或者设定的为none则表明hibernate在持久化某个对象时,不会持久化它的set集合中的自由态的对象。inverse属性我们可以理解为如果它的主控方在一端,那么它就会多一条update语句,这条update语句有时候是有用的 有时候是没用的,比如我们把上面代码中stu.setBanji(b)去掉,那么它就是有用的,反之它就是多余的,因为stu已经知道了这个关系.那为什么要把主控方放在多端,因为从性能考虑的,我们假设<set>里面有很多个自由态对象,那么是不是要多执行很多遍不必要的update
当然我们也要注意,把主控放放在多端,多端一定要知道这个关系,也就是一定要 stu.setBanji(b),否则将会出错。
(2)查询
@Test
public void delete(){
Stu stu=(Stu) session.get(Stu.class,22);
System.out.println(stu.getSname());
System.out.println(stu.getBanji().getBname());
Banji b=(Banji)session.get(Banji.class,8);
System.out.println(b.getBname());
}
查询没什么好说的 只是有一个属性要注意,lazy这个属性默认情况下是true也就是说,要用到关联对象时,再操作。如果为false时,如果我们查询出学生,则学生的班级属性里面已经封装好了,班级的实体类。
(3)删除
@Test
public void delete(){
Transaction tr=session.beginTransaction();
Banji b=(Banji) session.get(Banji.class,24);
session.delete(b);
tr.commit();
}
删除一个对象需要关注两个属性cascade和inverse这两属性,根据实际情况比如说,删除班级,首先得删除班级下的学生,于是cascade需要为all。如果删除学生(主控方),也就是它来维护关联双方之间的关系,所以对它的操作(插入,删除)会同时引发被控方的变化,所以这时候那么把关联属性清空.
(4)修改
修改就不演示了.
3.它的优点:
(1)orm对象关系映射,让程序员从繁琐的SQL解放出来,以面向对象的思想去操作数据库
(2)完整独立的事务机制
(3)良好的移植性,它是一个独立,系统的持久层框架。它和业务逻辑,已经数据库是相分离的所以,它可以和很多数据库配合使用。
(4)缓存机制,提高性能
4.它的缺点:
它的缺点是和优点相对的,正因为它的orm能够的简单,自动的对单一数据,少量数据持久化,所以当面临大量数据的时候,它的效能就不是那么的高,
当面临多表的时候,它的配置文件的编写,已经表与表之间的级联关系,就显的很复杂。
5.性能:
缓存是影响性能的关键因素,我们可以通过检索策略对性能进行优化