惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园 - 三生石上(FineUI控件)
D
DataBreaches.Net
博客园_首页
J
Java Code Geeks
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
罗磊的独立博客
腾讯CDC
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
B
Blog
D
Docker
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
A
About on SuperTechFans
博客园 - 聂微东
Stack Overflow Blog
Stack Overflow Blog
WordPress大学
WordPress大学
MyScale Blog
MyScale Blog
G
Google Developers Blog
博客园 - 司徒正美
aimingoo的专栏
aimingoo的专栏
小众软件
小众软件
Apple Machine Learning Research
Apple Machine Learning Research
博客园 - 叶小钗
M
MIT News - Artificial intelligence
Recent Announcements
Recent Announcements

博客园 - 樊凯

Weblogic10.3客户端jar文件 PHP5操作MySQL数据库 - 樊凯 - 博客园 Struts2拦截器 使用AppServ快速建立php运行环境 一个关于SpringSecurity很好的参考文档 Struts2.1.6 + Spring2.5+Hibernate3.2整合 JQuery和Struts实现Ajax文件上传 struts1.x+spring2.5+JPA(hibernate)整合 使用Apache的commons-codes加密 Spring备忘(涵盖Spring2.5) Spring备忘四(涵盖Spring2.5) Sping备忘三(涵盖Spring2.5) Spring备忘二(涵盖Spring2.5) - 樊凯 - 博客园 Spring备忘一(涵盖Spring2.5) ubuntu遇到的错误 Ubuntu命令(更新中) 异常java.lang.UnsupportedClassVersionError: Bad version number in .class file 根据ResultSetMetaData对象动态创建pojo或其集合(JDBC) 天生我牛必有用
Hibernate缓存
樊凯 · 2009-09-13 · via 博客园 - 樊凯

在Hibernate中提供了两种缓存来提升程序的性能,分别为一级缓存和二级缓存,也称为内置缓存和外置缓存。

一级缓存在Session中实现,当Session关闭时一级缓存就失效了。我们来看一个使用了来一级缓存的示例:

Session session = factory.openSession();
Student stu = (Student) session.get(Student.class, 21L);
Student stu2 = (Student) session.get(Student.class, 21L);
session.close();
 

我们在同一个Session中使用get方法获取同一个对象两次,当代码运行时,控制台只输出一条SQL语句,这就证明了一级缓存的作用,通过Session对象的contains方法来判断一个对象是否在一级缓存中。

Session session = factory.openSession();
Student stu = (Student) session.get(Student.class, 21L);
System.out.println(session.contains(stu));
Student stu2 = (Student) session.get(Student.class, 21L);
System.out.println(session.contains(stu2));
session.close();
 
在Session中还提供了clear方法,用于将一级缓存中的所有对象进行清除。使用evict方法将指定的对象从一级缓存中清除。
 
SessionFactory factory = config.buildSessionFactory();
Session session = factory.openSession();
Student stu = (Student) session.get(Student.class, 21L);
session.evict(stu);  //将stu从一级缓存中清除
Student stu2 = (Student) session.get(Student.class, 21L);
session.close();
 

上面的代码中由于将stu从一级缓存中清除,所以在控制台中会产生两条SQL语句。一级缓存由Hibernate来进行维护,一般不需要我们使用手工干预。

在Hibernate中二级缓存在SessionFactory中实现,由一个SessionFactory的所有Session实例所共享。Session在查找一个对象时,会首先在自己的一级缓存中进行查找,如果没有找到,则进入二级缓存中进行查找,如果二级缓存中存在,则将对象返回,如果二级缓存中也不存在,则从数据库中获得。

Hibernate并未提供对二级缓存的产品化实现,而是为第三方缓存组件的使用提供了接口,当前Hibernate支持的第三方二级缓存的实现如下:

EHCache

OSCache

SwarmCache

JBossTreeCache

在使用二级缓存之前需要进行一些配置(以EHCache为例)。首先将Hibernate开发包中lib目录下的ehcache-1.2.jar放到工程的build Path中。然后在Hibernate的配置文件hibernate.cfg.xml中添加如下配置项:

<property name="hibernate.cache.provider_class">
	net.sf.ehcache.hibernate.EhCacheProvider
</property>
 

在工程的classPath中建立EHCache的配置文件ehcache.xml。

<ehcache>
    <diskStore path="java.io.tmpdir"/>
    <defaultCache
        maxElementsInMemory="10000"eternal="false"timeToIdleSeconds="120"timeToLiveSeconds="120"overflowToDisk="true"/>
</ehcache>

① 缓存中最大允许保存的对象数量。

② 缓存中数据是否为常量。

③ 缓存数据钝化时间,单位为秒。

④ 缓存数据生存时间,单位为秒。

⑤ 内存不足时,是否启用磁盘缓存。

在需要进行二级缓存的持久化对象的映射文件中指定缓存的同步策略。

<hibernate-mapping>
<class name="com.zhaolongedu.vo.Student" table="t_student">
	<cache usage="read-only"/>  ①
		…
</class>
</hibernate-mapping>

① 指定缓存的同步策略。不同的缓存实现,对缓存的同步策略的支持也是不相同的。EHCache支持以下三种同步策略:

1. read-only:只读。对于不会发生改变的数据,可以使用只读性缓存。

2. read-write:可读写缓存。用于对数据同步要求严格的情况。

3. nonstrict-read-write:如果程序对并发访问下的数据同步要求不是很严格,且数据更新操作不频繁时可采用该缓存策略。

用下面的示例演示二级缓存的作用:

public static void main(String[] args) {
	Configuration config = new Configuration();
	config.configure();
	SessionFactory factory = config.buildSessionFactory();
	Session session = factory.openSession();
	Student stu = (Student) session.get(Student.class, 21L);
	session.close();
		
	Session session2 = factory.openSession();
	Student stu2 = (Student) session2.get(Student.class, 21L);
	session2.close();
}

程序的运行结果是输出一条SQL语句,说明二级缓存设置生效。SessionFactory对象中的evict用于将指定对象从二级缓存中删除。

Session session = factory.openSession();
Student stu = (Student) session.get(Student.class, 21L);
session.close();

factory.evict(Student.class);
		
Session session2 = factory.openSession();
Student stu2 = (Student) session2.get(Student.class, 21L);
session2.close();

此时上面的代码执行结果为输出两条SQL语句。