Hibernate学习小结

来源:互联网 发布:linux查看运行的进程 编辑:程序博客网 时间:2024/06/07 08:18

Hibernate学习小结

Java中的三大框架赫赫有名,Hibernate是其中之一,刚接触Hibernate的时候对它充满好奇,学习中出错最多的地方就是hibernate延迟加载,体会很深刻。

 一、Hibernate的优势所在?

1、实现面向对象的持久化,是对象关系映射框架。

2、对JDBC进行了非常轻量级的对象封装,简化了JDBC 繁琐的编码。

3、将JavaBean对象和数据库的表建立对应关系。

二、Hibernate的原理?

1、configuration配置。

2、创建SessionFactory。

3、打开session。

4、开始一个事务。

5、持久化操作。

6、提交事务。

7、关闭session

三、映射文件中有哪几种映射?

1、类和类的映射。

2、属性和主键的映射。

3、属性和普通字段的映射。

四、Hibernate中类之间关系的实现:类与类之间的关系主要体现在表与表之间的关系进行操作,它们都市对对象进行操作,我们程序中把所有的表与类都映射在一起,XML配置文件中如:

多对一:

<many-to-one name="type" class="entity.Type" fetch="select"> <column name="type_id" not-null="true" /> </many-to-one>

一对多:

<set name="records"><key column="book_id"></key><one-to-many class="entity.Record" /></set>

联合主键:

<composite-id>        <key-many-to-onename="book" column="book_id"class="entity.Book"></key-many-to-one>        <key-many-to-one name="stu"column="stu_id"class="entity.Student"></key-many-to-one></composite-id>

五、session的关闭问题:

频繁开闭Session会造成性能的浪费,而且关联的session关闭后可能是游离态,仍然无法延迟加载,所以可以将session和事务的开启和关闭放在测试或者调用者的开始和结尾。如用Junit测试时一个线程依次执行多个方法,故可以在所有方法调用前开启事务,在所有方法完成后再提交事务并关闭Session:

@BeforeClasspublic static void beforeClass() throws Exception {          HibernateUtil.currentSession().beginTransaction();}@AfterClasspublic static void afterClass() throws Exception {          HibernateUtil.currentSession().getTransaction().commit();          HibernateUtil.closeCurrentSession();}

六、三种状态之间的转换:

new产生的对象—瞬时态,通过save saveOrUpdate方法转换为持久态,通过delete方法可以将对象变回瞬时态。session关闭之后,原有的持久态就变成了游离态,游离态通过系列方法可重新回到持久态,并在事务提交的时候和数据库同步。session的get load方法可直接获得一个持久态对象。持久态和游离态的共同点在于,都有数据表的一行与之对应,不同的是,持久态在session范围内,而游离态不在session范围内。

 

七、Hibernate延迟加载机制所谓延迟加载就是当在真正需要数据的时候,才真正执行数据加载操作。

Hibernate默认的加载计划是:

1、关联对象和关联集合的默认加载计划是:延迟加载,即加载主对象时它们不会被立即加载,而是直到使用这些对象和集合时才发送SQL语句、获取数据、初始化对象和集合。

2、主对象本身是否延迟加载取决于使用的是load()方法还是其它方法,load()方法是延迟的,而get()方法或其它方法是立即的。

3、主对象的属性默认是被立即加载的。

例如以下代码:

Book book = (Book) session.get(Book.class, 64);//1System.out.println(book.getType().getName());//2

 说明:实体类Book的一个属性的类型是Type类的,当程序执行到1处时,这时并不会发起对关联数据的查询来加载关联数据,只有运行到2处时,真正的数据读取操作才会始。如果想让关联的数据立即加载可以通过改变默认加载计划的方式。

改变默认加载计划:通过修改对应类的实体映射文件,改变默认的加载计划。

<many-to-one name="type" class="entity.Type"fetch="select" lazy="false"> <column          name="type_id"not-null="true" /></many-to-one><set name="records" lazy="false">          <keycolumn="book_id"></key>          <one-to-manyclass="entity.Record" /></set>

这样做可以立即加载关联数据,但我们不建议这样做,因为这样配置之后,不管是否需要关联数据,Hibernate都会加载,这样会造成大量的内存浪费。最好是采用编程方式在特定情况下进行立即加载(也称热加载)。

属性上的延迟加载:Hibernate3开始增加了property节点的lazy属性,为特定的属性指定延迟加载计划,以避免主对象整体加载可能带来的性能浪费,尤其是针对大数据量的属性。

<many-to-one name="type" class="entity.Type"fetch="select" lazy="false"> <column          name="type_id"not-null="true" /></many-to-one><set name="records" lazy="false">          <keycolumn="book_id"></key>          <one-to-manyclass="entity.Record" /></set>

通过对<property>元素的lazy属性设置true来开启属性的延迟加载,在Hibernate3中为了实现属性的延迟加载

八、Hibernate一级缓存:

Hibernate一级缓存的生命周期跟Session的生命周期一样,所以也可以将Hibernate一级缓存称为Session缓存。Hibernate一级缓存是一个强制的高速缓存。get()方法会去一级缓存中查找获取数据(又称命中数据),并且将查询结果放置在一级缓存中。load()也一样。list()方法会将查询结果放置在一级缓存中,但是它不会去一级缓存中查找获取数据,原因是list()方法不是通过id加载的。iterate方法:

<many-to-one name="type" class="entity.Type"fetch="select" lazy="false"> <column          name="type_id"not-null="true" /></many-to-one><set name="records" lazy="false">          <keycolumn="book_id"></key>          <one-to-manyclass="entity.Record" /></set>

该语句只把ID的值放到迭代器中,当遍历的时候,会根据ID的值再去数据库中查,并且该语句会产生N+1次查询。

Session是么时候清理缓存?

1、程序调用Transaction的commit()方法时,commit()方法先清理缓存,在提交数据库的事务

2、程序调用session的find()或者iterate()时,如果缓存中的持久化对象的状态发生了变化,就会先清理缓存,保证查询结果能反映持久化对象的最新状态

3、当应用程序显示的调用Session的flush()方法时



原创粉丝点击