-
hibernate 的缓存使用问题5
问题描述见:
在测试Hibernate二级缓存的时候
把ehcache.xml和hibernate.cfg.xml里的相关二级缓存的配置 都删掉 ,
直接在hbm.xml中配置 <cache usage= "read-write " /> ,
发现查询结果看起来仍是通过缓存来查询的
因为sql没有打印两次
package com.vavi.test; import org.hibernate.Session; import com.vavi.dao.HibernateSessionFactory; import com.vavi.pojo.Tuser; public class Test { public static void main(String[] args) { Session sess = HibernateSessionFactory.getCurrentSession(); Tuser user_load = (Tuser) sess.load(com.vavi.pojo.Tuser.class, new Long(1)); System.out.println(user_load.getName()); sess.close(); sess = HibernateSessionFactory.getCurrentSession(); Tuser user_get = (Tuser) sess.get(com.vavi.pojo.Tuser.class, new Long(1)); System.out.println(user_get.getName()); sess.close(); } }
HibernateSessionFactory 是MyEclipse 生成的
问题补充:
package com.vavi.test;
/**
* 结论:Session级别的缓存 仅在当前session 生命期内有效
* 一旦该session关闭 ,再次查询时仍需要访问数据库
*/
import org.hibernate.Session;
import com.vavi.dao.HibernateSessionFactory;
import com.vavi.pojo.Tuser;
public class Test_SessionClose {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Session sess = HibernateSessionFactory.getCurrentSession();
Tuser user_load =(Tuser) sess.load(com.vavi.pojo.Tuser.class, new Long(1));
System.out.println(user_load.getName());
sess.close();
sess = HibernateSessionFactory.getCurrentSession();
Tuser user_get =(Tuser) sess.get(com.vavi.pojo.Tuser.class, new Long(1));
System.out.println(user_get.getName());
sess.close();
}
}
这段代码跟上面的一样
唯一 不同的地方就是 不在 Tuser.hbm.xml 加上 <cache usage="read-write" />
这时候打印的结果是 :
Hibernate: select tuser0_.ID as ID0_, tuser0_.NAME as NAME0_0_, tuser0_.AGE as AGE0_0_ from GHJ.TUSER tuser0_ where tuser0_.ID=?
ghj
Hibernate: select tuser0_.ID as ID0_, tuser0_.NAME as NAME0_0_, tuser0_.AGE as AGE0_0_ from GHJ.TUSER tuser0_ where tuser0_.ID=?
ghj
说明session cache 还是失效了的
按照您的说法
我打印了下 System.out.println("session:"+sess);
这两个程序(加不加 <cache usage="read-write" />
)都是 session:org.hibernate.impl.SessionImpl(<closed>)
根据这个打印结果并不能看出什么
所以关键是 这段话 <cache usage="read-write" />
不太清楚 他到底有什么作用 应该不是 一级缓存 二级缓存 或 查询缓存
最后谢谢您的解答 ^^
问题补充:
多谢gotothework的 回答
你说的这几种策略我也知道
但是关键是加上这段话后 <cache usage="read-write" />
不需要访问数据库 就可以直接出现结果了 (详细描述见上)
而我认为 这个查询结果不是 一级缓存 二级缓存 或 查询缓存 里面的内容
但是如果不是
hibernate 又是如何管理这部分缓存的
抑或还是我的理解有误?
问题补充:
To gotothework :
在调用sess.close()这个方法以前,一级缓存是一直有效的.所以应该是由一级缓存里调用出来的.
当你查询时,会首先从一级缓存中寻找,如果查找不到,还会从二级缓存中寻找,如果还未找到,就会从数据库中查询.
我明白
你见我第二个问题补充,现在问题是 其他配置(二级缓存 查询缓存 都不配置),仅在Tuser.hbm.xml 加上 <cache usage="read-write" />
打印结果表明: 第二次查询结果 没有访问数据库 就直接返回结果了
问题补充:
To gotothework :
在您说的这种情况下
hibernate是使用哪种缓存呢? 一级缓存?
但是如果同样的程序
不在 Tuser.hbm.xml 加上 <cache usage="read-write" />
仍是需要先后访问两次数据库的
所以这段 <cache usage="read-write" /> 代码作用很诡异
难道加了这段话就保存了一级缓存的数据?
您说的openSession()
我试了下
同时加上了 sess.contains(user_load) 和hashCode() 这个方法
package com.vavi.dao;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
//import com.vavi.dao.HibernateSessionFactory;
import com.vavi.pojo.Tuser;
public class SFTest {
public static void main(String[] args) {
SessionFactory sf = new Configuration().configure().buildSessionFactory();
Session sess = sf.openSession();
System.out.println(sess.hashCode());
Tuser user_load = (Tuser) sess.load(com.vavi.pojo.Tuser.class,
new Long(1));
System.out.println("sess.contains user_load? "+sess.contains(user_load));
System.out.println(user_load.getName());
sess.close();
System.out.println("sess.contains user_load? "+sess.contains(user_load));
sess =sf.openSession();
System.out.println(sess.hashCode());
Tuser user_get = (Tuser) sess.get(com.vavi.pojo.Tuser.class,
new Long(1));
System.out.println("sess.contains user_load? "+sess.contains(user_load));
System.out.println("sess.contains user_get? "+sess.contains(user_get));
System.out.println(user_get.getName());
sess.close();
System.out.println("sess.contains user_get? "+sess.contains(user_get));
}
}
打印结果如下:
31966667
sess.contains user_load? true
Hibernate: select tuser0_.ID as ID0_, tuser0_.NAME as NAME0_0_, tuser0_.AGE as AGE0_0_ from GHJ.TUSER tuser0_ where tuser0_.ID=?
ghj
sess.contains user_load? false
22375698
sess.contains user_load? false
sess.contains user_get? true
ghj
sess.contains user_get? false
所以这个现象就比较诡异了
发现sess关闭后,sess.contains(user_load)返回值是false的。
但是仍未查询数据库就获得结果了
问题补充:
哈哈 问题搞定 忘了hibernate 是默认启动二级缓存 以及使用 Cache provider: org.hibernate.cache.EhCacheProvider.
我上述的问题现象其实还是使用Hibernate的 二级缓存的
[main] (SettingsFactory.java:209) - Second-level cache: enabled
INFO [main] (SettingsFactory.java:213) - Query cache: disabled
INFO [main] (SettingsFactory.java:321) - Cache provider: org.hibernate.cache.EhCacheProvider
INFO [main] (SettingsFactory.java:228) - Optimize cache for minimal puts: disabled
INFO [main] (SettingsFactory.java:237) - Structured second-level cache entries: disabled
总结:
1、使用二级缓存的话 仅仅必须在 Tuser.hbm.xml 加上 <cache usage="read-write" />
其他设置使用的是Hibernate 里面jar包的默认配置文件
当然如果需要高级应用,那就需要自定义配置文件了
2、对于Hibernate,遇到不明白的问题,建议加上<property name="generate_statistics">true</property>
并打印debug级别日志
3、Session sess = HibernateSessionFactory.getCurrentSession(); 仍是获得新的session 实例的
同时 一级缓存(Session Cache)是在session.close() 调用后就失效的,跟当前没关系 (不知道理解有没有问题)
4、没有莫名其妙的问题,想起老大对我说的一句公告。 哈哈 ,这就是我中秋节的礼物了 ^^2008年9月13日 17:10
4个答案 按时间排序 按投票排序
-
采纳的答案
刚才是我理解错你的意思了,
Session sess = HibernateSessionFactory.getCurrentSession();
如果你这么去调用,将会把当前线程与Session绑定,而且在线程结束时,Hibernate会自动的关闭这个与线程绑定的Session,不需要你手动关闭.即使你手动的关闭也不会起作用,因为你当前的线程没有结束.所以,当你第二次调用Session sess = HibernateSessionFactory.getCurrentSession();
这个方法的时候,其实获得的Session与第一次获得的是同一个,这就是为什么第二次直接返回的结果,而没有去数据库中查询.
这里你可以试一下openSession(),他是每次都创建一个新的Session实例.2008年9月13日 20:58
-
Hibernate的一级缓存是必须使用的,既然你删除了二级缓存,那这里就应该用到了一级缓存,一级缓存是由Session来维护的,也就是说,在你Session开启的情况下,你的一级缓存一直有效,只有在你调用了Session的close()方法后,Session所维护的一级缓存才会失效,从楼主的代码来看
public static void main(String[] args) { Session sess = HibernateSessionFactory.getCurrentSession(); Tuser user_load = (Tuser) sess.load(com.vavi.pojo.Tuser.class, new Long(1)); System.out.println(user_load.getName()); sess.close(); sess = HibernateSessionFactory.getCurrentSession(); Tuser user_get = (Tuser) sess.get(com.vavi.pojo.Tuser.class, new Long(1)); System.out.println(user_get.getName()); sess.close(); }
在调用sess.close()这个方法以前,一级缓存是一直有效的.所以应该是由一级缓存里调用出来的.
当你查询时,会首先从一级缓存中寻找,如果查找不到,还会从二级缓存中寻找,如果还未找到,就会从数据库中查询.
不知道我这次说的对楼主是否有帮助,如果不明,非常高兴与你讨论2008年9月13日 19:47
-
这里的usage是缓存的策略,你可以根据你的需要来设置缓存策略,总共右种
transactional、 read-write、 nonstrict-read-write或 read-only。
只读缓存(Strategy: read only)
如果你的应用程序只需读取一个持久化类的实例,而无需对其修改, 那么就可以对其进行只读 缓存。这是最简单,也是实用性最好的方法。甚至在集群中,它也能完美地运作。
读/写缓存(Strategy: read/write)
如果应用程序需要更新数据,那么使用读/写缓存 比较合适。 如果应用程序要求“序列化事务”的隔离级别(serializable transaction isolation level),那么就决不能使用这种缓存策略。 如果在JTA环境中使用缓存,你必须指定hibernate.transaction.manager_lookup_class属性的值, 通过它,Hibernate才能知道该应用程序中JTA的TransactionManager的具体策略。 在其它环境中,你必须保证在Session.close()、或Session.disconnect()调用前, 整个事务已经结束。 如果你想在集群环境中使用此策略,你必须保证底层的缓存实现支持锁定(locking)。Hibernate内置的缓存策略并不支持锁定功能。
非严格读/写缓存(Strategy: nonstrict read/write)
如果应用程序只偶尔需要更新数据(也就是说,两个事务同时更新同一记录的情况很不常见),也不需要十分严格的事务隔离, 那么比较适合使用非严格读/写缓存策略。如果在JTA环境中使用该策略, 你必须为其指定hibernate.transaction.manager_lookup_class属性的值, 在其它环境中,你必须保证在Session.close()、或Session.disconnect()调用前, 整个事务已经结束。
事务缓存(transactional)
Hibernate的事务缓存策略提供了全事务的缓存支持, 例如对JBoss TreeCache的支持。这样的缓存只能用于JTA环境中,你必须指定 为其hibernate.transaction.manager_lookup_class属性。
大体就是这样,希望对楼主有所帮助2008年9月13日 19:14
-
配置文件都删了应该不会启用的,可能是读到一级缓存的内容了,虽然sess.colse()会清空一级缓存,你再测一下吧,把session打印出来看一下,看一下里面有没有Tuser bean,有的话就是一级缓存了,如下:
public class Test {
public static void main(String[] args) {
Session sess = HibernateSessionFactory.getCurrentSession();
Tuser user_load = (Tuser) sess.load(com.vavi.pojo.Tuser.class,
new Long(1));
System.out.println(user_load.getName());
sess.close();
System.out.println("session:"+sess);
sess = HibernateSessionFactory.getCurrentSession();
Tuser user_get = (Tuser) sess.get(com.vavi.pojo.Tuser.class,
new Long(1));
System.out.println(user_get.getName());
sess.close();
}
}2008年9月13日 17:41
相关推荐
### 深入理解Hibernate缓存 #### 一、Hibernate缓存概述 Hibernate作为一款流行的Java持久层框架,为开发者提供了高效且灵活的数据访问能力。其中,缓存机制是Hibernate性能优化的重要组成部分之一。理解Hibernate...
Hibernate缓存.docHibernate缓存.doc
**Hibernate缓存深入详解** 在Java企业级应用开发中,Hibernate作为一款强大的对象关系映射(ORM)框架,极大地简化了数据库操作。然而,随着应用规模的扩大,数据访问性能成为了一个不可忽视的问题。这时,...
### Hibernate缓存技术研究 #### 一、引言 Hibernate是一种强大的对象-关系映射(Object-Relational Mapping,简称ORM)工具,主要用于Java环境下的应用程序。它能够将应用程序中的对象模型映射到关系型数据库的表...
Java Hibernate缓存深入详解
Hibernate缓存机制是提高应用程序性能的关键技术之一,它通过存储数据副本减少对物理数据库的访问。缓存可以分为两层:第一级缓存和第二级缓存。 **第一级缓存**是内置在Session中的,它是不可卸载的,也称为...
- **性能监控工具**:利用JProfiler、VisualVM等工具,定期分析应用性能瓶颈,识别缓存使用不当、SQL查询低效等问题,并进行针对性优化。 - **持续集成测试**:在开发流程中集成性能测试环节,确保每次代码提交都...
【Hibernate缓存深入详解】 在Java的持久化框架Hibernate中,缓存机制是提升系统性能的关键因素。它位于Hibernate应用和数据库之间,减少了对数据库的直接访问,从而提高了应用程序的运行速度。缓存中存储的是...
使用Hibernate二级缓存需要根据实际情况选择,适用于数据不会被第三方修改、数据量适中的情况。如果数据可能被第三方修改,需要手动管理缓存一致性。如果数据量过大,可能需要评估是否适合使用缓存,以防止内存压力...
Hibernate 是一个流行的对象关系映射(ORM)框架,它允许Java...通过理解Hibernate缓存和事务管理,以及如何有效地执行查询,开发者可以创建高效、健壮的Java应用程序,降低与数据库交互的复杂性,同时提升系统性能。
### Hibernate缓存机制及优化策略 #### 一、概述 Hibernate作为一款优秀的对象关系映射(ORM)框架,在Java开发领域被广泛应用于数据库操作。它提供了丰富的缓存机制来提高应用性能并降低数据库访问压力。本文将...
**标题:“Hibernate缓存与Spring事务详解”** 在IT领域,尤其是Java开发中,Hibernate作为一款流行的ORM(对象关系映射)框架,极大地简化了数据库操作。而Spring框架则以其全面的功能,包括依赖注入、AOP(面向切...
关于hibernate缓存的一个ppt课件,60+幻灯片,有需要的可以看一下
本文将详细讲解Hibernate缓存的原理、类型以及使用方法。 ### 1. Hibernate缓存概述 缓存是存储在内存中的临时数据,当应用程序需要数据时,首先从缓存中查找,而不是直接查询数据库。这样可以减少网络延迟,提高...
Hibernate缓存原理及调优策略 Hibernate缓存原理调优策略
这篇博客文章“hibernate缓存ehcache用法”可能详细介绍了如何在Hibernate中配置和使用Ehcache。 首先,我们需要理解什么是缓存。缓存是一种存储技术,用于临时保存经常访问的数据,以减少对主存储器(如数据库)的...
#### Hibernate缓存机制概述 Hibernate提供了两种缓存级别:一级缓存和二级缓存。 - **一级缓存**:存在于Session范围内,用于存储实体的实例和状态。当一个实体被加载到Session时,其状态会保存在一级缓存中,...
7. **示例代码**:通过提供的源码,我们可以学习如何在实际项目中配置和使用Hibernate缓存,包括创建缓存配置、声明缓存区域、启用查询缓存等。 总的来说,这个教程应该涵盖了Hibernate缓存的基础知识,包括一级...