一级缓存:

  又称为session缓存,它和session生命周期相同,周期非常短.是事务级别的缓存:

  还是以Book和Category这两个表为例,我们用代码观察一个缓存的存在:

假设现在我要去查询id=1的Book信息:

        List<Book> list =(List) session.createQuery("from Book").list();
System.out.println(list.get().getName());
Book book = (Book)session.get(Book.class, );
System.out.println(book.getName());

我这里先查询了所有的Book,打印出了index=0,即id=1的那本书的书名,接着用get方法再次获取了id=1的Book,我们看一下控制台的打印信息:

  通过打印信息我们能发现一个现象,当第二次我们使用get(..)方法去查询时,我们如愿得到了书名,但却没有select语句,说明了什么问题?说明了使用get()方法获取id=1的Book时,hibernate并没有去访问数据库,而是在某一个地方就得到了这个id=1的Book的信息,不难发现,我们第一次使用createQuery()时,其实已经得到了这条Book的信息,而hibernate将这些信息放到了一个缓存里,当执行查询语句时,hibernate没有着急的立即访问数据库去查询,而是先到这个缓存里去找找有没有他所要查询的数据,如果有的话,那就皆大欢喜了,不需要访问数据库,提高了效率,而这个缓存.就是我们所说的一级缓存,也叫session缓存.

  同时我们也能知道,get方法使用了一级缓存,用get查询数据时,首先检查缓存中是否有该数据,如果有,直接从缓存中获取该数据直接返回,如果没有,再去访问数据库查找.load也支持一级缓存,但是同时load同时也支持延迟加载.要注意.

  接下继续测试代码:

List<Book> list =(List) session.createQuery("from Book").list();
System.out.println(list.get().getName()); list =(List) session.createQuery("from Book").list();
System.out.println(list.get().getName())

在代码中,我们执行了两次session.createQuery(),如果只打印一条sql语句,说明list查询也支持一级缓存,打印结果是这样:

很不幸,控制台打印出了两条sql语句,这就说明了:

  list查询不支持一级缓存,但list查询会把返回的结果保存到session缓存,同理uniqueResult()查询也是如此.

接下来继续测试:

List<Book> list =(List) session.createQuery("from Book").list();
System.out.println(list.get().getName()); Iterator<Book> iter = session.createQuery("from Book").iterate();
while(iter.hasNext()){
System.out.println(iter.next().getName());
}

这里我们第一次使用list查询得到所有Book信息,然后用iterate查询,得到一个包含所有Book的迭代器集合,那么他会不会支持一级缓存,这是控制台打印的信息:

  乍一看,第二次查询的时候依然打出了sql语句,看来iterate查询是不会先去session中查找的了,但是仔细观察第一条sql语句,可以发现,它仅仅查询了Book的id,但依然打印出了每本书的书名.说明了,iterate依然是在缓存中查询的数据,所以,iterate是支持一级缓存的,同样它执行的查询,也会把返回结果保存到session缓存中.

` 现在再来看一下管理session的几个方法.

  1. session.flush():一般是结合事务对象Transaction用的,用来清理缓存,执行sql,避免内存溢出,假设你要保存十万条数据,你肯定不希望当保存到九万条的时候程序出错,然后事务回滚,导致一条数据都没有保存上,这时候你可以每保存一千条数据就执行一次session.flush(),这样的话,每保存一千条数据,就会执行到数据库,然后清理一下session缓存.
  2. session.evict(...);从session缓存中干掉你指定的某一个对象.
  3. session.clear():将当前session缓存中保存的所有对象统统干掉.

下面用代码演示一下evict,和clear方法:

     Book book =(Book) session.get(Book.class,);
System.out.println(book.getName());
session.evict(book);
//b表示干掉session中保存的所有对象,当然也包括Book对象
//session.clear()
book =(Book) session.get(Book.class,);
System.out.println(book.getName());

按照我们的设想,由于执行第二次查询之前,我们通过session.evict(book)方法,干掉了book对象,再次查询时会去访问数据库,来看一下控制台打印结果是不是这样的:

果然如此,跟我们料想的一样.

最新文章

  1. Bootstrap Metronic 学习记录(一)简介
  2. event.target指向谁?
  3. App界面交互设计规范
  4. MyBatis insert返回主键(sqlserver2008)
  5. Oracle Order Management DropShip Flow for R12
  6. Hive学习之六 《Hive进阶— —hive jdbc》 详解
  7. 配置managed server
  8. ok6410 u-boot-2012.04.01移植五支持DM9000
  9. python 带小数点时间格式化
  10. filter()和find()的区别
  11. angular2学习笔记3
  12. python之路--内置模块02
  13. JDK8安装与配置
  14. git撤销本地提交但未push的记录
  15. Visual Studio 2008 添加MScomm控件的方法
  16. 文件完整性hash验证demo(python脚本)
  17. 2018.10.18 poj2187Beauty Contest(旋转卡壳)
  18. Five reasons phosphorene may be a new wonder material
  19. python 文件读取方法详解
  20. Qt下Doxygen使用

热门文章

  1. Linux_10个需要了解的Linux网络和监控命令(转)
  2. 【转】GitHub 排名前 100 的安卓、iOS项目简介
  3. 科学计算软件——Octave安装
  4. Jexus 支持PHP的三种方式
  5. .NET Core 构建配置文件从 project.json 到 .csproj
  6. ReactJS入门(三)—— 顶层API
  7. Python黑帽编程 3.5 DTP攻击
  8. ASP.Net请求处理机制初步探索之旅 - Part 4 WebForm页面生命周期
  9. Redis高可用分布式内部交流(九)
  10. [.net 面向对象程序设计进阶] (20) 反射(Reflection)(上)利用反射技术实现动态编程