Hibernate中的事务管理以及缓存管理<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
l事务的概念(前面已经讲述)
lHibernate中的Session缓存(前面已经讲述)
lHibernate中的二级缓存以及二级缓存的缓存策略
lQuery查询缓存
lQuery.list()、iterator()深入
l悲观锁定(PessimisticLocking)
l乐观锁定(OptimisticLocking)
二级缓存
前面,我们讲述过Session级别的缓存。
Session级别的缓存,它的生命周期与Session的生命周期一致。当Session关闭时,其缓存将失效。
这里,进一步讨论Hibernate提供的另一种缓存机制-二级缓存,它比Session级别的缓存更高一级,是属于SessionFactory级别的缓存,该缓存将被属于同一个SessionFactory级别的所有Session共享。
二级缓存为每个类(或集合),配置集群、或JVM级别(SessionFactory级别)的缓存。你甚至可以为之插入一个集群的缓存。注意,缓存永远不知道其他应用程序对持久化仓库(数据库)可能进行的修改(即使可以将缓存数据设定为定期失效)。
Hibernate的Sessionlevel缓存随着Session生命周期起始与消灭。
以第一个Hibernate中的范例来说,在未使用二级缓存的情况下,如果使用以下的程序片段来查询数据:
Sessionsession=sessionFactory.openSession();
Useruser1=(User)session.load(User.class,newInteger(1));
user1.getName();
session.close();
session=sessionFactory.openSession();
Useruser2=(User)session.load(User.class,newInteger(1));
user2.getName();
session.close();
则Hibernate将会使用以下的SQL来进行数据查询:
Hibernate:selectuser0_.idasid0_,user0_.nameasname0_0_,user0_.ageasage0_0_fromuseruser0_whereuser0_.id=?
Hibernate:selectuser0_.idasid0_,user0_.nameasname0_0_,user0_.ageasage0_0_fromuseruser0_whereuser0_.id=?
由于Session被关闭,Sessionlevel无法起作用,所以第二次的查询仍必须向数据库直接查询。
Hibernate二级缓存可以跨越数个Session,二级缓存由同一个SessionFactory所建立的Session所共享,因而又称为SessionFactorylevel缓存。
Hibernate本身并未提供二级缓存的实现,而是藉由第三方(Third-party)产品来实现,Hibernate预设使用EHCache作为其二级缓存的实现,在最简单的情况下,您只需在Hibernate下撰写一个ehcache.xml作为EHCache的资源定义档,可以在Hibernate下载档案中的etc目录下找到一个已经撰写好的ehcache.xml,以下撰写最简单的ehcache.xml:
ehcache.xml
<ehcache>
<diskStorepath="java.io.tmpdir"/>
<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="true"
/>
</ehcache>
将这个文件放在Hibernate项目Classpath可存取到的路径下,接着重新运行上面的程序片段,您可以发现Hibernate将使用以下的SQL进行查询:
Hibernate:selectuser0_.idasid0_,user0_.nameasname0_0_,user0_.ageasage0_0_fromuseruser0_whereuser0_.id=?
二级缓存被同一个SessionFactory所建立的Session实例所共享,所以即使关闭了Session,下一个Session仍可使用二级缓存,在查询时,Session会先在Sessionlevel缓存中查询看有无数据,如果没有就试着从二级缓存中查询数据,查到数据的话就直接返回该条数据,所以在上例中,第二次无需再向数据库进行SQL查询。
如果打算清除二级缓存的资料,可以使用SessionFactory的evict()方法,例如:
sessionFactory.evict(User.class,user.getId());
如果打算在Hibernate中使用其它第三方产品进行缓存,则可以在hibernate.cfg.xml中定义hibernate.cache.provider_class属性,例如:
hibernate.cfg.xml
<hibernate-configuration>
<session-factory>
....
<propertyname="hibernate.cache.provider_class">
org.hibernate.cache.HashtableCacheProvider
</property>
....
</session-factory>
</hibernate-configuration>
通过在hibernate.cache.provider_class属性中指定org.hibernate.cache.CacheProvider的某个实现的类名,你可以选择让Hibernate使用哪个缓存实现。Hibernate打包一些开源缓存实现,提供对它们的内置支持(见下表)。除此之外,你也可以实现你自己的实现,将它们插入到系统中。注意,在3.2版本之前,默认使用EhCache作为缓存实现,但从3.2起就不再这样了。
![]()
HashtableCache是Hibernate自己所提供的二级缓存实现,不过性能与功能上有限,只用于开发时期的测试之用。
可以在映射文件中指定缓存策略,使用<cache>卷标在映像实体或Collection上设定缓存策略,例如:
User.hbm.xml
<hibernate-mapping>
<classname=“com.cstp.User"table="user">
<cacheusage="read-only"/>
<idname="id"column="id"type="java.lang.Integer">
<generatorclass="native"/>
</id>
<propertyname="name"column="name"type="java.lang.String"/>
<propertyname="age"column="age"type="java.lang.Integer"/>
</class>
</hibernate-mapping>
类或者集合映射的“<cache>元素”可以有下列形式:
<cache
usage="transactional|read-write|nonstrict-read-write|read-only"
region="RegionName"
include="all|non-lazy"
/>
usage(必须)说明了缓存的策略:transactional、read-write、nonstrict-read-write或read-only。
region(可选,默认为类或者集合的名字(classorcollectionrolename))指定第二级缓存的区域名(nameofthesecondlevelcacheregion)
include(可选,默认为all)non-lazy当属性级延迟抓取打开时,标记为lazy="true"的实体的属性可能无法被缓存
另外(首选?),你可以在hibernate.cfg.xml中指定<class-cache>和<collection-cache>元素。
这里的usage属性指明了缓存并发策略(cacheconcurrencystrategy)。
可以设定的策略包括read-only、read-write、nonstrict-read-write与transactional,并不是每一个第三方缓存实现都支持所有的选项,每一个选项的使用时机与支持的产品,可以直接参考Hibernate官方参考手册的20.2.TheSecondLevelCache
只读缓存(Strategy:readonly)
如果你的应用程序只需读取一个持久化类的实例,而无需对其修改,那么就可以对其进行只读缓存。这是最简单,也是实用性最好的方法。甚至在集群中,它也能完美地运作。
<classname="eg.Immutable"mutable="false">
<cacheusage="read-only"/>
....
</class>
读/写缓存(Strategy:read/write)
如果应用程序需要更新数据,那么使用读/写缓存比较合适。如果应用程序要求“序列化事务”的隔离级别(serializabletransactionisolationlevel),那么就决不能使用这种缓存策略。如果在JTA环境中使用缓存,你必须指定hibernate.transaction.manager_lookup_class属性的值,通过它,Hibernate才能知道该应用程序中JTA的TransactionManager的具体策略。在其它环境中,你必须保证在Session.close()、或Session.disconnect()调用前,整个事务已经结束。如果你想在集群环境中使用此策略,你必须保证底层的缓存实现支持锁定(locking)。Hibernate内置的缓存策略并不支持锁定功能。
<classname="eg.Cat"....>
<cacheusage="read-write"/>
....
<setname="kittens"...>
<cacheusage="read-write"/>
....
</set>
</class>
非严格读/写缓存(Strategy:nonstrictread/write)
如果应用程序只偶尔需要更新数据(也就是说,两个事务同时更新同一记录的情况很不常见),也不需要十分严格的事务隔离,那么比较适合使用非严格读/写缓存策略。如果在JTA环境中使用该策略,你必须为其指定hibernate.transaction.manager_lookup_class属性的值,在其它环境中,你必须保证在Session.close()、或Session.disconnect()调用前,整个事务已经结束。
事务缓存(transactional)
Hibernate的事务缓存策略提供了全事务的缓存支持,例如对JBossTreeCache的支持。这样的缓存只能用于JTA环境中,你必须指定为其hibernate.transaction.manager_lookup_class属性。
没有一种缓存提供商能够支持上列的所有缓存并发策略。下表中列出了各种提供器、及其各自适用的并发策略。
![]()
Query查询缓存
Hibernate的Sessionlevel缓存会在使用Session的load()方法时起作用,在设定条件进行查询时,无法使用缓存的功能,现在考虑一种情况,您的数据库表格中的数据很少变动,在使用Query查询数据时,如果表格内容没有变动,您希望能重用上一次查询的结果,除非表格内容有变动才向数据库查询。
您可以开启Query的缓存功能,因为要使用Query的缓存功能必须在两次查询时所使用的SQL相同,且两次查询之间表格没有任何数据变动下才有意义,所以Hibernate预设是关闭这个功能的,如果您觉得符合这两个条件,那么可以试着开启Query缓存功能来看看效能上有无改进。
先来看看下面的查询程序片段:
Sessionsession=sessionFactory.openSession();
Stringhql="fromUser";
Queryquery=session.createQuery(hql);
Listusers=query.list();
for(inti=0;i<users.size();i++){
Useruser=(User)users.get(i);
System.out.println(user.getName());
}
query=session.createQuery(hql);
users=query.list();
for(inti=0;i<users.size();i++){
Useruser=(User)users.get(i);
System.out.println(user.getName());
}
session.close();
在不启用Query缓存的情况下,Hibernate会使用两次SQL向数据库查询数据:
Hibernate:selectuser0_.idasid,user0_.nameasname0_,user0_.ageasage0_fromuseruser0_
zhangy
hhp
Hibernate:selectuser0_.idasid,user0_.nameasname0_,user0_.ageasage0_fromuseruser0_
zhangy
hhp
如果打算启用Query缓存功能,首先在hibernate.cfg.xml中设定hibernate.cache.use_query_cache属性:
hibernate.cfg.xml
<hibernate-configuration>
<session-factory>
....
<propertyname="hibernate.cache.use_query_cache">true</property>
....
</session-factory>
</hibernate-configuration>
然后在每次建立Query实例时,执行setCacheable(true):
Sessionsession=sessionFactory.openSession();
Stringhql="fromUser";
Queryquery=session.createQuery(hql);
//使用Query缓存
query.setCacheable(true);
Listusers=query.list();
for(inti=0;i<users.size();i++){
Useruser=(User)users.get(i);
System.out.println(user.getName());
}
query=session.createQuery(hql);
//使用Query缓存
query.setCacheable(true);
users=query.list();
for(inti=0;i<users.size();i++){
Useruser=(User)users.get(i);
System.out.println(user.getName());
}
session.close();
Hibernate在启用Query缓存后,会保留执行过的查询SQL与查询结果,在下一次查询时会看看SQL是否相同,并看看对应的数据库表格是否有变动(Update/Delete/Insert),如果SQL相同且数据库也没有变动,则将Query缓存中的查询结果返回,上面的程序片段将使用一次SQL查询,第二次查询时直接返回缓存中的结果.
Query上有list()与iterate()方法,两者的差别在于开启Query缓存之后,list()方法在读取数据时,会利用到Query缓存,而iterate()则不会使用到Query缓存功能,而是直接从数据库中再查询数据。
来看看下面的程序:
Sessionsession=sessionFactory.openSession();
Queryquery=session.createQuery("fromUser");
query.setCacheable(true);; c
分享到:
相关推荐
Hibernate学习笔记 Hibernate学习笔记 Hibernate学习笔记 Hibernate学习笔记
Hibernate学习笔记整理 以下是 Hibernate 框架的详细知识点: Hibernate 介绍 Hibernate 是一个 ORM(Object-Relational Mapping)框架,用于将 Java 对象映射到数据库表中。它提供了一个简洁的方式来访问和操作...
《Hibernate学习笔记特别详细》 Hibernate,作为一款开源的Object-Relational Mapping(ORM)框架,为Java开发者提供了强大的数据库操作支持。它简化了数据库访问的复杂性,使得开发人员可以像操作对象一样操作...
hibernate 学习笔记精要hibernate 学习笔记精要hibernate 学习笔记精要hibernate 学习笔记精要
在本篇《Hibernate学习笔记》中,我们将深入探讨Hibernate这一流行的Java对象关系映射(ORM)框架。Hibernate允许开发者以面向对象的方式处理数据库操作,极大地简化了数据存取的复杂性。以下是一些关键知识点: 1....
这套笔记是我学习Hibernate,进行相关技术点训练时记录下来的,其中包括技术点说明与相关事例,拿出来与大家分享。
【Java相关课程系列笔记之十四Hibernate学习笔记】 Hibernate是一个开源的对象关系映射(ORM)框架,它极大地简化了Java应用程序对数据库的操作。本笔记将详细阐述Hibernate的核心概念、使用方法和特性。 一、...
《Hibernate学习笔记——马士兵教程解析》 在Java开发领域,ORM(Object-Relational Mapping)框架的使用已经非常普遍,其中Hibernate作为一款优秀的ORM框架,因其强大的功能和易用性深受开发者喜爱。本文将根据马...
hibernate概述,hibernate入门Demo,hibernate配置文件详解(全局配置,实体类映射配置),配置实体规则,核心API详解(Configuration,sessionFactory,session,Transaction),hibernate中的对象状态以及刷新能缓存机制 ...
**Hibernate学习笔记与总结** Hibernate 是一款开源的对象关系映射(ORM)框架,它为Java开发者提供了一种在关系数据库上操作对象数据的便捷方式。本文将深入探讨Hibernate的核心概念、配置、实体类、映射文件、...
### 马士兵Hibernate学习笔记知识点总结 #### 一、课程内容概览 - **HelloWorld**:通过简单的示例程序介绍如何启动一个基于Hibernate的Java项目。 - **Hibernate原理模拟**:解释O/R Mapping的概念及其重要性。 -...
传智播客 汤阳光 Hibernate 学习笔记,非常详细的hibernate学习资料!
Hibernate是一款强大的Java持久...通过阅读这份“Hibernate API帮助文档”和“Hibernate学习笔记”,你将能够深入理解Hibernate的工作原理,掌握其API的使用,并能在实际项目中有效地利用Hibernate进行数据持久化操作。
### Hibernate 学习笔记知识点概览 #### 一、Hibernate 概述 - **定义**:Hibernate 是一款开源的对象关系映射(ORM)框架,它实现了将 Java 应用程序中的对象模型映射到关系型数据库中的记录。通过 ORM 技术,...
在深入探讨Hibernate学习笔记第二天的源码之前,我们先来理解一下Hibernate的核心概念。Hibernate是一个开源的对象关系映射(ORM)框架,它允许Java开发者将数据库操作转化为对象模型,大大简化了数据访问层的开发...
**hibernate学习笔记第四天源码解析** 在hibernate学习的过程中,第四天通常会深入探讨实体类、映射文件、配置文件以及查询语言等方面的内容。这些是hibernate框架的基础,也是开发者掌握持久化操作的关键。让我们...
### 马士兵Hibernate学习笔记知识点总结 #### 一、HelloWorld示例 - **目的**:通过简单的示例理解Hibernate的基本使用流程。 - **步骤**: - 创建Java项目`hibernate_0100_HelloWorld`。 - 建立库依赖,包括...