理解 Hibernate 一级缓存

Hibernate 一级缓存默认是打开,不需要任何的配置。实际上,你无法强制禁止它的使用。

如果你理解了一级缓存实际上和会话是关联的,就很容易理解一级缓存。总所周知,会话是当我们需要时从会话工厂创建并且一旦会话关闭,缓存就会丢失。相似的,一级缓存与会话对象相关联,在会话存活期间是可用的。相同应用中的不同会话是无法相互访问的。

重点##

  • 一级缓存和会话相关联,应用中的会话无法知道其他会话中的缓存
  • 缓存的范围是在会话范围内。一旦会话被关闭,缓存将永远消失
  • 一级缓存默认是打开的,并无法禁止
  • 第一次查询一个实体会从数据库中检索,并被存放在与 hibernate 会话关联的一级缓存中
  • 如果在一个会话中再次查询该实体,它将从一级缓存中加载,不会发送 sql 查询到数据库
  • 加载的实体可以从会话中被移除,通过使用 evict() 方法。如果实体已经使用 evict 下次加载该实体将会再次调用数据库查询
  • 整个会话缓存可以通过 clear() 方法移除。它将移除缓存中的所有实体

从一级缓存检索的例子

在下面的例子中,将通过 hibernate 会话从数据库检索 Department 实体。多次检索该实体,观察 sql 语句是否被发出去。

//Open the hibernate session
Session session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction(); //fetch the department entity from database first time
DepartmentEntity department = (DepartmentEntity) session.load(DepartmentEntity.class, new Integer(1));
System.out.println(department.getName()); //fetch the department entity again
department = (DepartmentEntity) session.load(DepartmentEntity.class, new Integer(1));
System.out.println(department.getName()); session.getTransaction().commit();
HibernateUtil.shutdown(); Output:
Hibernate: select department0_.ID as ID0_0_, department0_.NAME as NAME0_0_ from DEPARTMENT department0_ where department0_.ID=?
Human Resource
Human Resource

从输出来看,第二次 session.load() 语句并没有执行 select 查询,而是直接加载 department 实体。说明实体对象却是被缓存了。

新会话测试一级缓存

如果实体已经在一个会话中被获取,在新会话中,该实体将再次从数据库中获取。

//Open the hibernate session
Session session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction(); Session sessionTemp = HibernateUtil.getSessionFactory().openSession();
sessionTemp.beginTransaction();
try
{
//fetch the department entity from database first time
DepartmentEntity department = (DepartmentEntity) session.load(DepartmentEntity.class, new Integer(1));
System.out.println(department.getName()); //fetch the department entity again
department = (DepartmentEntity) session.load(DepartmentEntity.class, new Integer(1));
System.out.println(department.getName()); department = (DepartmentEntity) sessionTemp.load(DepartmentEntity.class, new Integer(1));
System.out.println(department.getName());
}
finally
{
session.getTransaction().commit();
HibernateUtil.shutdown(); sessionTemp.getTransaction().commit();
HibernateUtil.shutdown();
} Output: Hibernate: select department0_.ID as ID0_0_, department0_.NAME as NAME0_0_ from DEPARTMENT department0_ where department0_.ID=?
Human Resource
Human Resource Hibernate: select department0_.ID as ID0_0_, department0_.NAME as NAME0_0_ from DEPARTMENT department0_ where department0_.ID=?
Human Resource

从输出可以发现及时 department 实体已经被存储在会话中,但是 sessionTemp 会话还是发出了一条数据库查询语句。说明不同会话之间的缓存是相互不可见的。

将实体对象从一级缓存中移除

虽然无法禁用 hibernate 一级缓存,但是如果需要的话,可以移除该缓存对象。通过使用一下两个方法:

  • evict()
  • clear()

evict() 用于移除会话中的指定缓存对象,clear() 方法则用于移除会话中的所有缓存对象。一下代码展示移除一个缓存对象和移除所有缓存对象。

//Open the hibernate session
Session session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
try
{
//fetch the department entity from database first time
DepartmentEntity department = (DepartmentEntity) session.load(DepartmentEntity.class, new Integer(1));
System.out.println(department.getName()); //fetch the department entity again
department = (DepartmentEntity) session.load(DepartmentEntity.class, new Integer(1));
System.out.println(department.getName()); session.evict(department);
//session.clear(); department = (DepartmentEntity) session.load(DepartmentEntity.class, new Integer(1));
System.out.println(department.getName());
}
finally
{
session.getTransaction().commit();
HibernateUtil.shutdown();
} Output: Hibernate: select department0_.ID as ID0_0_, department0_.NAME as NAME0_0_ from DEPARTMENT department0_ where department0_.ID=?
Human Resource
Human Resource Hibernate: select department0_.ID as ID0_0_, department0_.NAME as NAME0_0_ from DEPARTMENT department0_ where department0_.ID=?
Human Resource

从输出结果很明显可以看出,evict() 方法将 department 实体从一级缓存中移除,所以他再次从数据库中获取。

本文内容来自:http://howtodoinjava.com/hibernate/understanding-hibernate-first-level-cache-with-example/。本文只是翻译以及润色

欢迎转载,但请注明本文链接,谢谢你。

2016.9.21 9:08

hibernate一级缓存的更多相关文章

  1. Hibernate一级缓存(基于查询分析)

    首先我们应该弄清什么是hibernate缓存:hibernate缓存是指为了降低应用程序对物理数据源的访问频次,从而提高应用程序的运行性能的一种策略.我们要将这个跟计算机内存或者cpu的缓存区分开. ...

  2. hibernate一级缓存及对象的状态

    hibernate中实体类对象的状态 在hibernate中实体类对象有三种状态 (1)瞬时态(临时态) 瞬时态:即我们自己创建一个对象,还没有保存到数据库就叫临时态,其实也可以说是对像没有id值,跟 ...

  3. Hibernate一级缓存(补)

    ------------------siwuxie095                                 什么是缓存         缓存是介于应用程序和永久性数据存储源(如:硬盘上的 ...

  4. Hibernate一级缓存测试分析

    Hibernate 一级缓存测试分析 Hibernate的一级缓存就是指Session缓存,此Session非http的session会话技术,可以理解为JDBC的Connection,连接会话,Se ...

  5. 转载 hibernate一级缓存和二级缓存的区别

    文章来源:http://blog.csdn.net/defonds/article/details/2308972     hibernate一级缓存和二级缓存的区别 缓存是介于应用程序和物理数据源之 ...

  6. Hibernate一级缓存和三种状态

    Hibernate一级缓存又称session缓存,生命周期很短,跟session生命周期相同. 三种状态:1.transient(瞬时态):刚new出来的对象,既不在数据库中,也不在session管理 ...

  7. hibernate一级缓存的源码初窥

    hibernate的一级缓存的存在使得hibernate可以在操作实体化对象的时候减少对于数据库的访问.hibernate的一级缓存实际上就是指的session缓存,它的生命周期和session相同. ...

  8. Hibernate 一级缓存的陷阱

    最近公司的应用经常报OOM,一开始我以为是公司业务数据太多,导致内存不够,所以只是简单的把容器的内存加大.撑了几天后这个错仍然被报出来.后来我仔 细分析过项目代码后,没有发现有任何引起内存泄漏的地方. ...

  9. Hibernate <一级缓存>

    Hibernate缓存分为三级: 一级缓存:基于事务级别(内存)的缓存,也可以成为session级别缓存 二级缓存:依赖于第三方,当请求一个对象时,先在缓存里面查找,如果没有就执行查询语句 查询缓存: ...

随机推荐

  1. C# 4.0 新特性dynamic (待学习)

    随便翻看了一下dynamic,在网上拷贝了一个例子,先贴出来等有空了再慢慢消化 static void Main(string[] args) { dynamic d = new MyDynamicO ...

  2. 白皮 Chapter 1

    6.29 今天主要做了一些1.5中的小结和练习,果然换语言思路也要跟着变么…各种不爽啊不爽… scanf各种忘记&,还有各种忘记return 0… average temperature su ...

  3. doctype声明的重要性-------这绝对是ie的坑, 与angular无关, 我错怪你啦

    今天开发一个页面,  自己写页面, 自己实现功能. 因为以往需求都没有要求兼容ie9, 所以并未发现此坑. 今天就记录下来. 贴图对比 ie9 chrome 如图, ie9界面显示错误. 起初以为是a ...

  4. java基础之 多态

    在面向对象编程(Object-Oriented Programming, OOP)中,多态机制无疑是其最具特色的功能,甚至可以说,不运用多态的编程不能称之为OOP.这也是为什么有人说,使用面向对象语言 ...

  5. JQuery ajax 异步传一个数组到 .net后台

    可能使用JQuery Ajax传值到后台一个字符串,或者序列化后的表单大家都使用过,但是某些项目,需要我们一次传值一个数组到后台,这个时候有什么好的办法呢? 1.JS将数组转换为一个字符串,然后传值到 ...

  6. java.io.IOException: Cannot run program "jad"

    今天调试google tag manager, 需要看看google analytics source code,无奈没有源码,装个一个插件ejad 还是不行: java.io.IOException ...

  7. CSS中box-sizing属性的理解与部分用法

    今天看了一些关于box-sizing的一些资料,在这里整理一下,希望也能对大家有所帮助. box-sizing是CSS的一个属性,很好的解决了盒模型的相关问题.CSS中的盒模型(Box model)分 ...

  8. JAVA开发相关

    JAVA开发相关1. IntelliJ IDEA开发工具熟练使用2. Maven3. Spring框架(IoC.AOP) 1)数据库相关MyBatis 2)数据库连接池 3)事务.多数据源.跨数据库分 ...

  9. js 表单验证方法二

    function ckReight () { var pass = true; var new = $("#new"); if( new.find('input[name=name ...

  10. 【其他】win7创建wifi热点共享给手机使用

    出门在外,有时候网络有诸多不便,需要用笔记本创建wifi热点给手机用:本人测试xp怎么配置都不好使,但win7有可行的方案,不依赖第三方软件. 详述如下: 场景一:win7 + A(PC机)(用无线连 ...