Hibernate缓存级别教程

开始使用Hibernate的人们常见的问题之一就是性能,如果您没有太多的Hibernate经验,您会发现应用程序变慢的速度。 如果启用sql跟踪,您将看到有多少查询被发送到数据库,而这些查询几乎不需要Hibernate知识就可以避免。 在当前文章中,我将解释如何使用休眠查询缓存来避免应用程序和数据库之间的通信量。

Hibernate提供了两个缓存级别:

  • 一级缓存是会话缓存。 对象被缓存在当前会话中,并且它们仅在会话关闭之前是活动的。
  • 只要会话工厂处于活动状态,第二级缓存就存在。 请记住,在Hibernate情况下,二级缓存不是对象树。 对象实例不被缓存,而是存储属性值。

在简要介绍了一下Hibernate缓存之后(让我知道这很简短),让我们看一下什么是查询缓存以及如何与二级缓存相关联。

查询缓存负责将作为参数提供的查询和值的组合作为键进行缓存,并将查询执行返回的对象的标识符列表作为值进行缓存。 注意,使用查询缓存也需要二级缓存,因为从缓存(即标识符列表)获取查询结果时, Hibernate将使用二级缓存的标识符加载对象。

概括起来,作为一个概念性的模式,给出下一个查询:“ from country from country>:number “,第一次执行后, Hibernate缓存将包含下一个虚构值(请注意,number参数设置为1000):

L2快取
[
id:1,{name ='Spain',人口= 1000,...。} id:2,{name ='德国',人口= 2000,...} …。 QueryCache [{来自人口>:number的国家/地区,1000},{id:2}]

因此,在开始使用查询缓存之前,我们需要配置第二级缓存。
首先,您必须确定要使用的缓存提供程序。 对于此示例,选择了Ehcache ,但请参阅Hibernate文档以获取所有支持的提供程序的完整列表。

要配置二级缓存,请设置下一个休眠属性:

hibernate.cache.provider_class = org.hibernate.cache.EhCacheProvider
hibernate.cache.use_structured_entries = true
hibernate.cache.use_second_level_cache = true

如果您使用注释方法,请使用以下方法注释可缓存的实体:

@可缓存
@Cache(用法= CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)

可以看到在这种情况下,缓存并发策略是NONSTRICT_READ_WRITE ,但是根据缓存提供者的不同,可以遵循其他策略,例如TRANSACTIONAL,READ_ONLY ………请查看Hibernate文档的缓存部分,以选择最适合您需求的策略。

最后添加Ehcache依赖项:

<依赖性>
<groupId> net.sf.ehcache </ groupId>
<artifactId> ehcache-core </ artifactId> <version> 2.5.0 </ version> </ dependency> <依赖性> <groupId> org.hibernate </ groupId> <artifactId> hibernate-ehcache </ artifactId> <version> 3.6.0.Final </ version> </ dependency>

现在已配置了二级缓存,但未配置查询缓存 ; 无论如何,我们离目标不远。

hibernate.cache.use_query_cache属性设置为true

对于每个可缓存的查询,我们必须在查询创建期间调用setCachable方法:

List <Country> list = session.createQuery(“来自人口> 1000的国家/地区”).setCacheable(true).list();

为了使示例更实用,我已经使用Spring Framework上传了完整的查询缓存示例。 为了清楚地了解查询缓存的工作原理,我使用了一个在ensembl.org中托管的公共数据库。 Ensembl项目为脊椎动物和其他真核生物建立了基因组数据库,并在线免费提供此信息。 在此示例中,对dna表的查询被缓存。

首先进行Hibernate配置:

@Configuration
public class HibernateConfiguration {@Value("#{dataSource}")private DataSource dataSource;@Beanpublic AnnotationSessionFactoryBean sessionFactoryBean() {Properties props = new Properties();props.put("hibernate.dialect", EnhancedMySQL5HibernateDialect.class.getName());props.put("hibernate.format_sql", "true");props.put("hibernate.show_sql", "true");props.put("hibernate.cache.provider_class", "org.hibernate.cache.EhCacheProvider");props.put("hibernate.cache.use_structured_entries", "true");props.put("hibernate.cache.use_query_cache", "true");props.put("hibernate.cache.use_second_level_cache", "true");props.put("hibernate.hbm2ddl.auto", "validate");AnnotationSessionFactoryBean bean = new AnnotationSessionFactoryBean();bean.setAnnotatedClasses(new Class[]{Dna.class});  bean.setHibernateProperties(props);bean.setDataSource(this.dataSource);bean.setSchemaUpdate(true);return bean;}}

这是一个简单的Hibernate配置,使用前面说明的属性来配置二级缓存。

实体类是代表DNA序列的实体。

@Entity(name="dna")
@Cacheable
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class Dna {@Idprivate int seq_region_id;private String sequence;public int getSeq_region_id() {return seq_region_id;}public void setSeq_region_id(int seq_region_id) {this.seq_region_id = seq_region_id;}@Columnpublic String getSequence() {return sequence;}public void setSequence(String sequence) {this.sequence = sequence;}}

为了尝试查询缓存 ,我们将实现一项测试,其中多次执行同一查询。

@Autowired
private SessionFactory sessionFactory;@Test
public void fiftyFirstDnaSequenceShouldBeReturnedAndCached() throws Exception {for (int i = 0; i < 5; i++) {Session session = sessionFactory.openSession();session.beginTransaction();Time elapsedTime = new Time("findDna"+i);List<Dna> list = session.createQuery("from dna").setFirstResult(0).setMaxResults(50).setCacheable(true).list();session.getTransaction().commit();session.close();elapsedTime.miliseconds(System.out);for (Dna dna : list) {System.out.println(dna);}}
}

我们可以看到我们正在返回前五十个dna序列,如果执行它,您将看到打印了从查询创建到提交事务之间的经过时间。 如您所料,仅第一次迭代就需要大约5秒钟来获取所有数据,而其他迭代只需数毫秒。

查询迭代之前的foreach行将通过控制台打印对象标识符。 如果仔细观察,这些标识符将不会在所有执行期间重复。 这个事实只是向您显示Hibernate缓存不会保存对象而是保存属性值,并且每次都会创建对象本身。

最后一点,请记住,默认情况下, Hibernate不缓存关联。

现在,在编写查询之后,考虑它是否将包含静态数据以及是否将经常执行。 在这种情况下, 查询缓存是您的朋友,可以使Hibernate应用程序运行得更快。

下载代码

参考:来自JCG合作伙伴的 Hibernate缓存级别教程   在一个罐子统治他们所有博客的亚历克斯·索托。


翻译自: https://www.javacodegeeks.com/2012/02/hibernate-cache-levels-tutorial.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/373361.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java方法执行的时间_计算Java中任意一个方法的执行时间的工具类

1 packagealgorithm.study.utils;23 importjava.lang.reflect.Method;45 /**6 * This class is getting a method execute time and provide some other functions.7 *8 *authorygh 2017年2月24日9 */10 public classMethodExecuteTimeUtils {1112 /**13 * Get a method execut…

如何在 IIS 中设置 HTTPS 服务

Windows Server2008、IIS7启用CA认证及证书制作完整过程 这篇文章介绍了如何安装证书申请工具&#xff1b; 如何在iis创建证书申请&#xff1b; 如何使用iis申请证书生成的txt文件&#xff0c;在工具中开始申请证书&#xff1b; 如何导出证书&#xff1b; 以及在网站中开始使用…

Android之卫星菜单的实现

卫星菜单是现在一个非常受欢迎的“控件”&#xff0c;很多Android程序员都趋之若鹜&#xff0c;预览如下图。传统的卫星菜单是用Animation实现的&#xff0c;需要大量的代码&#xff0c;而且算法极多&#xff0c;一不小心就要通宵Debug。本帖贴出用属性动画Animator来实现卫星菜…

Java中的WADL:温和的介绍

WADL&#xff08; Web应用程序描述语言 &#xff09;对REST而言&#xff0c;WSDL对SOAP而言。 这种语言的仅仅存在引起了很多争议&#xff08;请参阅&#xff1a; 我们需要WADL吗&#xff1f; 或者 需要 WADL还是不需要WADL &#xff09;。 我可以想到使用WADL的一些合法用例&a…

类成员函数模板特化

//类成员函数模板特化 #include <stdio.h> class A{ public:template <class T>void Print(){printf("A template\n");} };template<> void A::Print<int>(){printf("int\n"); }int main(){A a;a.Print<double>();a.Print&l…

为云量身定制您的服务

相信大家都听说过Amazon的AWS。作为业内最为成熟的云服务提供商&#xff0c;其运行规模&#xff0c;稳定性&#xff0c;安全性都已经经过了市场的考验。时至今日&#xff0c;越来越多的应用被部署在了AWS之上。这其中不乏Zynga及Netflix这样著名的服务。 然而这一切并没有停滞不…

在Vaadin和JSF之间选择

随着最新版本的Primefaces 3.0的发布&#xff0c;JSF终于达到了前所未有的成熟度和实用性&#xff0c;使其与其他流行的Rich Internet Applications&#xff08;RIA&#xff09;选项如Google Web Toolkit&#xff08;GWT&#xff09;&#xff0c;ExtJS&#xff0c;Vaadin&#…

20145202马超《信息安全系统设计基础》实验二总结

[实验二]&#xff08;http://www.cnblogs.com/nizaikanwoma/p/6131778.html&#xff09; 转载于:https://www.cnblogs.com/tuolemi/p/6131987.html

java 连接ldap_ldap java 连接demo

public class LDAPHelper {/*** LDAP可以理解为一个多级目录&#xff0c;这里&#xff0c;表示要连接到那个具体的目录*/private final String baseDn "ouPeople,dcchangyeyi,dccom";private LdapContext ctx null;private final Control[] connCtls null;private…

flask开发restful api系列(1)

在此之前&#xff0c;向大家说明的是&#xff0c;我们整个框架用的是flask sqlalchemy redis。如果没有开发过web&#xff0c;还是先去学习一下&#xff0c;这边只是介绍如果从开发web转换到开发移动端。如果flask还不是很熟悉&#xff0c;我建议先到这个网站简单学习一下&am…

Apache Commons Lang StringUtils

因此&#xff0c;认为最好谈论我喜欢的另一个Java库。 它已经存在了一段时间&#xff0c;也许不是最令人兴奋的库&#xff0c;但是它非常有用。 我可能每天都使用它。 org.apache.commons.lang.StringUtils StringUtils是Apache Commons Lang&#xff08; http://commons.apac…

JEE7:展望新时代

计划于2012年下半年发布的Java EE 7预计的JSR都已启动并正在运行。 Java EE 7发行版是日期驱动的&#xff0c;它将反映该行业迁移到云中时不断变化的需求&#xff1a;任何未准备就绪的内容将推迟到Java EE 8中使用 。 这是Java EE 7平台中不同规范的关键功能的更新和摘要。 1。…

Cocos2d-JS项目之UI界面的优化

测试环境&#xff1a; iphone4、iOS6.1.2、chrome 37.2062.60&#xff0c;Cocos2d-js 3.6 之前写了不少&#xff0c;实际项目也按这个去优化了&#xff0c;也有效果&#xff0c;但到最后才发现&#xff0c;尼玛&#xff0c;之前都搞错了&#xff0c;之所以有效果是歪打正着。。…

java数_java大数

java大数还是很好用的&#xff01;基本加入&#xff1a;import java.math.BigInteger;import jave.math.BigDecimal;分别是大数和大浮点数。首先读入可以用&#xff1a;Scanner input new Scanner(System.in);BigInteger a input.nextBigInteger();这样读还是很方便的当然还有…

【Qt之Quick模块】6. QML语法详解_2类型系统

描述 在QML文档中对象层次结构的定义中可能使用的类型可以来自各种来源。它们可能是: 由QML语言原生提供通过QML模块通过c注册由QML模块作为QML文档提供 此外&#xff0c;应用程序开发人员可以通过直接注册c类型&#xff0c;或者通过在QML文档中定义可重用的组件(然后可以导…

JS显示当前时间(包含农历时间)

时间格式&#xff1a; JavaScript代码&#xff1a; var sWeek new Array("星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六");var dNow new Date();var CalendarData new Arra…

Maven原型创建技巧

我最近需要为姜黄SOA项目创建一些Maven原型。 对于不了解的人来说&#xff0c; Maven原型是一种基于一些预先罐装的项目模板生成项目的方法。 对于当前的姜黄SOA原型&#xff0c;它将创建一个多模块Maven项目&#xff0c;该项目包含Interface和Service项目以及基本的WSDL和适当…

MyBatis操作指南-与Spring集成(基于注解)

转载于:https://www.cnblogs.com/weilu2/p/mybatis_spring_integration_basic_on_annotation.html

Windows mysql boost_Win7下Boost库的安装

Boost库是C领域公认的经过千锤百炼的知名C类库&#xff0c;涉及编程中的方方面面&#xff0c;简单记录一下使用时的安装过程1.boost库的下载boost库官网主页&#xff1a;www.boost.org2.安装将下载的压缩包解压到指定的目录3.建立编译工具bjam.exe在源码目录下执行bootstrap.ba…

5.2与终端进行对话

Linux提供了一个特殊的设备 /dev/tty &#xff0c;该设备始终是指向当前终端或者当前的登录会话。 FILE* output fopen("/dev/tty", "w"); //向终端写入字符串 fprintf(output, "%s\n", "world"); FILE* input fopen("/dev/tty…