SSH学习-Hibernate懒惰加载&缓存机制

Hibernate查询会先从一级缓存session中查询数据,如果session中没有会从sessionfactory中查找数据,如果前面两个都没有将从DB中查数据,这就是Hibernate的缓存机制,这样可以降低应用程序与物理数据源的交互频率,提高应用程序的性能。另外懒惰加载,就是尽可能晚的将数据库中的数据加载到内存中来,需要查询时查询数据,不需要查询的数据暂时就不查询。

一级缓存session管理方法

(1)evict(Object):将对象Object从session中清除掉,从持久状态进入到游离状态

(2)clear():将session中的所有对象都清除掉

(3)flush():将缓存中的数据与数据库中的数据进行同步

(4)contains(Object):判断session中是否包含某个对象Object

(6)将保存的数据放到session:save()

(7)将查询的数据放到session:get(),load(),HQL查询

下面以一个案例进行分析,先使用get方法到一个对象存到session中,然后再重复一遍get动作,比较两个对象是否相同,如果相同说明第二次是从缓存中取出。

具体的hibernate.cfg.xml,表和实体类参考上一篇博客,这里直接调用测试方法进行测试,看看两次get得到的对象是否是同一个内存地址,如果是true说明就是同一对象。

package TestCase;

import java.util.List;
import java.util.Set;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.junit.Test;

import Entity.book;
import Entity.user;

/**
 * 测试Hibernate关联查询
 * @author yangchaolin
 */
public class testHibernate {

      public static Session getSession() {
          //读取hibernate.cfg.xml配置文件
          Configuration cfg=new Configuration();
          cfg.configure("hibernate.cfg.xml");
          //创建sessionfactory
          SessionFactory factory=cfg.buildSessionFactory();
          //创建session
          Session session=factory.openSession();
          return session;
      }

      //测试session缓存机制
      @Test
      public void testSession() {
          //获取session
          Session session=getSession();
          //开启事务
          Transaction trans=session.beginTransaction();
          trans.begin();
          //执行持久层操作
          user u1=(user) session.get(user.class, 1);//查询id为1的user
          //提交事务
          //trans.commit();
          //重复获取user对象的操作
          user u2=(user) session.get(user.class, 1);
          System.out.println("两个是否相同"+(u1==u2));
          /**
           * 测试发现结果为true,说明二次取得是保存在session中的数据
           */
          //关闭session
          session.close();
      }
}

测试结果:

从测试结果来看,第二次获取是从session一级缓存中获取的,并不是从DB中取出新存到内存中的对象,两者内存地址一致,输出结果为true。

懒惰加载

参考获取user为1的数据后,先打印user的id和name属性,后面再打印user的book属性,控制台发现先查询得到user 的id和name,当后面需要输出book时,再从数据库查询book,说明数据查询分了2次,不是一次性查询得到,这种现象就是懒惰加载。

映射文件中配置lazy属性到set标签下

      <!-- lazy设置为false,代表不懒惰加载,默认是懒惰加载 -->
      <set name="books" lazy="true"><!-- 实体类对应属性名 -->
        <key column="user_id"></key>
        <one-to-many class="Entity.book"></one-to-many>
      </set>
package TestCase;

import java.util.List;
import java.util.Set;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.junit.Test;

import Entity.book;
import Entity.user;

/**
 * 测试Hibernate关联查询
 * @author yangchaolin
 *
 */
public class testHibernate {

      public static Session getSession() {
          //读取hibernate.cfg.xml配置文件
          Configuration cfg=new Configuration();
          cfg.configure("hibernate.cfg.xml");
          //创建sessionfactory
          SessionFactory factory=cfg.buildSessionFactory();
          //创建session
          Session session=factory.openSession();
          return session;
      }

      //测试获取user id为1的用户的信息
      @Test
      public void test() {
          //读取hibernate.cfg.xml配置文件
          Configuration cfg=new Configuration();
          cfg.configure("hibernate.cfg.xml");
          //创建sessionfactory
          SessionFactory factory=cfg.buildSessionFactory();
          //创建session
          Session session=factory.openSession();
          //创建一个事务并开启事务
          Transaction trans=session.getTransaction();
          trans.begin();
          //开始执行持久层操作
          user user=(user) session.get(user.class, 1);//1代表user的id属性值
          System.out.println(user.getId());
          System.out.println(user.getName());
          Set<book> books=user.getBooks();
          for(book book:books) {
              System.out.println(book);
          }
          //关闭session
          session.close();
      }      

}

打印结果:

当将set标签下lazy设置为true,可以看出来先查询出来id和name,当需要打印book时,才查询books属性,它的查询分了两次,这就是懒惰加载,你不需要我不加载你需要时我再加载。

现在有个问题,如果第二次查询时,session提前关闭了会怎么样?结果是第二次将查询不到数据,为了避免因为懒惰加载和session提前关闭对查询结果的影响,struts2中有一个filter专门用于提前开启session,避免因为session提前关闭查询不到数据的情况,后面有机会再了解。

结论

Hibernate下无论是缓存机制还是懒惰加载,都是为了提高性能,因为其减少了应用程序对数据源的访问。

原文地址:https://www.cnblogs.com/youngchaolin/p/10909771.html

时间: 2024-10-11 10:35:11

SSH学习-Hibernate懒惰加载&缓存机制的相关文章

hibernate懒加载

16.懒加载 性能: 发出的sql语句越少,性能越高 方法: 1.懒加载 2.抓取策略 3.缓存策略 4.HQL语句   懒加载 1.类的懒加载 1.利用session.load方法可以产生代理对象 2.在session.load方法执行的时候并不发出sql语句 3.在得到其一般属性的时候发出sql语句 4.只针对一般属性有效,针对标示符属性是无效的 5.默认情况就是懒加载  2.集合的懒加载 <set name=""  lazy="" cascasd=&qu

关于ViewPager的适配器之——pagerAdapter加载缓存页面的机制

ViewPager有很多的适配器,如pagerAdapter,FragmentPagerAdapter等, 今天我想重点谈的是关于pagerAdapter加载缓存页面的机制的问题. 首先,使用pagerAdapter一般需要重写它的四个未实现的方法分别是: 1.  getCount(){} //得到总数 2.    //实例化页面,  相当于BaseAdapter等适配器中的 getView()方法 返回想要显示的对象(内容) // 不同之处是:这里需要把这些对象(内容)一一添加到adapter

深入java虚拟机学习 -- 类的加载机制(续)

昨晚写 深入java虚拟机学习 -- 类的加载机制 都到1点半了,由于第二天还要工作,没有将上篇文章中的demo讲解写出来,今天抽时间补上昨晚的例子讲解. 这里我先把昨天的两份代码贴过来,重新看下: class Singleton { private static Singleton singleton = new Singleton(); //第一份代码的位置 public static int counter1; public static int counter2=0; private s

Hibernate懒加载策略

所谓懒加载(lazy)就是延时加载,就是当在真正需要数据的时候,才真正执行数据加载操作 至于为什么要用懒加载呢,就是当我们要访问的数据量过大时,明显用缓存不太合适,因为内存容量有限 ,为了减少并发量,减少系统资源的消耗,我们让数据在需要的时候才进行加载,这时我们就用到了懒加载. 在通过JDBC操作数据时,我们只能通过SQL语句来加载我们所需要的数据,但是到了Hibernate世界中(确切的说,是到了对象关系映射的世界中),由于有O-R Mapping的帮助,我们拥有了更多的自由以及更多的方法,H

hibernate懒加载(转载)

http://blog.csdn.net/sanjy523892105/article/details/7071139 懒加载详解 懒加载为Hibernate中比较常用的特性之一,下面我们详细来了解下懒加载的原理和注意事项 Load()方法的懒加载原理 在Hibernate中,查询方法有两个,分别是get()和load(),这两种方法的不同就是load()拥有懒加载的特性.Load()方法就是在查询某一条数据的时候并不会直接将这条数据以指定对象的形式来返回,而是在你真正需要使用该对象里面的一些属

调查管理系统 -(6)自定义Struts2的拦截器&amp;自定义UserAware接口&amp;Action中模型赋值问题&amp;Hibernate懒加载问题

1.对于一些功能,如我的调查或新建调查等,只有用户登录后才能进行操作,因此必须对用户是否登录进行判断.当用户登录后才能使用相应的功能,如果没有登录则需为用户导航到登录页面让其进行登录.这个功能可以通过自定义Struts2的拦截器来完成. 2.当用户登录之后,由于是将用户的信息保存在session中的.这样当一些Action中需要用到当前登录的用户的信息时需要手动的从session中获取,不太方便,因此我们声明了一个UserAware接口(即用户关注,类似于Struts2中的SessionAwar

Hibernate懒加载异常解决方案总结

[什么是Hibernate懒加载异常] 我们所说的懒加载也被称为延迟加载,它在查询的时候不会立刻访问数据库,而是返回代理对象,当真正去使用对象的时候才会访问数据库,可以有效的降低数据库访问次数和内存使用量.懒加载为Hibernate中比较常用的特性之一,Hibernate 通过默认采取懒加载机制来降低系统的内存开销,提高系统性能.但这也使很多初学者使用Hibernate时容易出现懒加载异常. [出现懒加载异常的原因] 这个异常出现的原因主要是使用懒加载机制加载数据时,hibernate在从数据库

Android-Universal-Image-Loader (图片异步加载缓存库)对Bitmap的优化处理

转载请注明出处:http://blog.csdn.net/u011733020 前言: 前面两篇分别介绍了: Android-Universal-Image-Loader (图片异步加载缓存库)的使用配置 Android-Universal-Image-Loader (图片异步加载缓存库)的源码解读 通过前两篇,我们了解了 UIL的使用配置,UIL将服务器上的一张图片保存到本地,加载到内存的过程,以及UIL对DiscCache和MemoryCache的策略,但是还有一部分比较重要,因为它是我们的

OGEngine学习笔记---资源加载

声音管理兼容各种音频文件格式,比特率和样本率 OGEngine开源引擎兼容各种音频视频文件格式,并且引用了硬件加速技术,来对音频文件进行io读取,简化了资源的加载和读取写入的过程,大幅度减少应用卡顿.无响应的状况出现. 一个背景音乐 多个音效 OGEngine开源引擎在同一时间只能播放一首背景音乐,但是能同时播放多个音效. 首先自定义一个枚举类ConfigData,用来存放背景音乐key和音效key. public class ConfigData { /** 背景音乐*/ public sta