热门标签 | HotTags
当前位置:  开发笔记 > 数据库 > 正文

java中hibernate二级缓存详解

Hibernate的二级缓存 一、缓存概述 缓存(Cache): 计算机领域非常通用的概念。它介于应用程序和永久性数据存储源(如

Hibernate的二级缓存

一、缓存概述

缓存(Cache): 计算机领域非常通用的概念。它介于应用程序和永久性数据存储源(如硬盘上的文件或者数据库)之间,其作用是降低应用程序直接读写永久性数据存储源的频率,从而提高应用的运行性能。缓存中的数据是数据存储源中数据的拷贝。缓存的物理介质通常是内存

hibernate中提供了两个级别的缓存

第一级别的缓存是 Session 级别的缓存,它是属于事务范围的缓存。这一级别的缓存由 hibernate 管理的,一般情况下无需进行干预

第二级别的缓存是 SessionFactory 级别的缓存,它是属于进程范围的缓存

Hibernate 的缓存可以分为两类:

内置缓存: Hibernate 自带的, 不可卸载. 通常在 Hibernate 的初始化阶段, Hibernate 会把映射元数据和预定义的 SQL 语句放到 SessionFactory 的缓存中, 映射元数据是映射文件中数据的复制, 而预定义 SQL 语句时 Hibernate 根据映射元数据推到出来的. 该内置缓存是只读的.

外置缓存(二级缓存): 一个可配置的缓存插件. 在默认情况下, SessionFactory 不会启用这个缓存插件. 外置缓存中的数据是数据库数据的复制, 外置缓存的物理介质可以是内存或硬盘

二、理解二级缓存的并发访问策略

三、配置进程范围内的二级缓存(配置ehcache缓存)

1 拷贝ehcache-1.5.0.jar到当前工程的lib目录下

依赖 backport-util-concurrent 和 commons-logging

2 开启二级缓存

true

3 要指定缓存的供应商

 
    org.hibernate.cache.EhCacheProvider

4 指定使用二级缓存的类

方法一 在使用类的*.hbm.xml配置

选择需要使用二级缓存的持久化类, 设置它的二级缓存的并发访问策略, 元素的 cache 子元素表明 Hibernate 会缓存对象的简单属性, 但不会缓存集合属性, 若希望缓存集合属性中的元素, 必须在 元素中加入 子元素

方法二  在hibernate.cfg.xml文件中配置(建议)

  
  
  
  
 
  
  

5  配置ehcache默认的配置文件ehcache.xml(名字固定)(放在类路径下)

 
 
  
  
 

四、 测试

package com.sihai.hibernate3.test; 
 
import java.util.Iterator; 
import java.util.List; 
 
import org.hibernate.Query; 
import org.hibernate.Session; 
import org.hibernate.Transaction; 
import org.junit.Test; 
 
import com.sihai.hibernate3.demo1.Customer; 
import com.sihai.hibernate3.demo1.Order; 
import com.sihai.utils.HibernateUtils; 
 
public class HibernateTest6 { 
  
 @Test 
 // 查询缓存的测试 
 public void demo9(){ 
  Session session = HibernateUtils.getCurrentSession(); 
  Transaction tx = session.beginTransaction(); 
   
  Query query = session.createQuery("select c.cname from Customer c"); 
  // 使用查询缓存: 
  query.setCacheable(true); 
  query.list(); 
   
  tx.commit(); 
   
  session = HibernateUtils.getCurrentSession(); 
  tx = session.beginTransaction(); 
   
  query = session.createQuery("select c.cname from Customer c"); 
  query.setCacheable(true); 
  query.list(); 
   
  tx.commit(); 
 } 
  
 @SuppressWarnings("unused") 
 @Test 
 // 更新时间戳 
 public void demo8(){ 
  Session session = HibernateUtils.getCurrentSession(); 
  Transaction tx = session.beginTransaction(); 
   
  Customer customer = (Customer) session.get(Customer.class, 2); 
  session.createQuery("update Customer set cname = '奶茶' where cid = 2").executeUpdate(); 
   
  tx.commit(); 
   
  session = HibernateUtils.getCurrentSession(); 
  tx = session.beginTransaction(); 
   
  Customer customer2 = (Customer) session.get(Customer.class, 2); 
   
  tx.commit(); 
 } 
  
 @SuppressWarnings("all") 
 @Test 
 // 将内存中的数据写到硬盘 
 public void demo7(){ 
  Session session = HibernateUtils.getCurrentSession(); 
  Transaction tx = session.beginTransaction(); 
   
  List list = session.createQuery("from Order").list(); 
   
  tx.commit(); 
 } 
  
 @Test 
 // 一级缓存的更新会同步到二级缓存: 
 public void demo6(){ 
  Session session = HibernateUtils.getCurrentSession(); 
  Transaction tx = session.beginTransaction(); 
   
  Customer customer = (Customer) session.get(Customer.class, 1); 
  customer.setCname("芙蓉"); 
   
  tx.commit(); 
   
  session = HibernateUtils.getCurrentSession(); 
  tx = session.beginTransaction(); 
   
  Customer customer2 = (Customer) session.get(Customer.class, 1); 
   
  tx.commit(); 
 } 
  
 @SuppressWarnings("unchecked") 
 @Test 
 // iterate()方法可以查询所有信息. 
 // iterate方法会发送N+1条SQL查询.但是会使用二级缓存的数据 
 public void demo5(){ 
  Session session = HibernateUtils.getCurrentSession(); 
  Transaction tx = session.beginTransaction(); 
   
  // N+1条SQL去查询. 
  Iterator iterator = session.createQuery("from Customer").iterate(); 
  while(iterator.hasNext()){ 
   Customer customer = iterator.next(); 
   System.out.println(customer); 
  } 
   
  tx.commit(); 
   
  session = HibernateUtils.getCurrentSession(); 
  tx = session.beginTransaction(); 
   
  iterator = session.createQuery("from Customer").iterate(); 
  while(iterator.hasNext()){ 
   Customer customer = iterator.next(); 
   System.out.println(customer); 
  } 
   
  tx.commit(); 
 } 
  
 @SuppressWarnings("unchecked") 
 @Test 
 // 查询所有.Query接口的list()方法. 
 // list()方法会向二级缓存中放数据,但是不会使用二级缓存中的数据. 
 public void demo4(){ 
  Session session = HibernateUtils.getCurrentSession(); 
  Transaction tx = session.beginTransaction(); 
   
  // 查询所有客户: 
  // list方法会向二级缓存中放入数据的. 
  List list = session.createQuery("from Customer").list(); 
  for (Customer customer : list) { 
   System.out.println(customer.getCname()); 
  } 
  tx.commit(); 
   
  session = HibernateUtils.getCurrentSession(); 
  tx = session.beginTransaction(); 
   
  // Customer customer = (Customer) session.get(Customer.class, 1);// 没有发生SQL ,从二级缓存获取的数据. 
  // list()方法没有使用二级缓存的数据. 
  list = session.createQuery("from Customer").list(); 
  for (Customer customer : list) { 
   System.out.println(customer.getCname()); 
  } 
   
  tx.commit(); 
 } 
  
 @Test 
 // 二级缓存的集合缓冲区特点: 
 public void demo3(){ 
  Session session = HibernateUtils.getCurrentSession(); 
  Transaction tx = session.beginTransaction(); 
   
  Customer customer = (Customer) session.get(Customer.class, 1); 
  // 查询客户的订单. 
  System.out.println("订单的数量:"+customer.getOrders().size()); 
   
  tx.commit(); 
   
  session = HibernateUtils.getCurrentSession(); 
  tx = session.beginTransaction(); 
   
  Customer customer2 = (Customer) session.get(Customer.class, 1); 
  // 查询客户的订单. 
  System.out.println("订单的数量:"+customer2.getOrders().size()); 
   
  tx.commit(); 
 } 
  
 @SuppressWarnings("unused") 
 @Test 
 // 配置二级缓存的情况 
 public void demo2(){ 
  Session session = HibernateUtils.getCurrentSession(); 
  Transaction tx = session.beginTransaction(); 
   
  Customer customer1 = (Customer) session.get(Customer.class, 1);// 发送SQL. 
   
  Customer customer2 = (Customer) session.get(Customer.class, 1);// 不发送SQL. 
   
  System.out.println(customer1 == customer2); 
   
  tx.commit(); 
   
  session = HibernateUtils.getCurrentSession(); 
  tx = session.beginTransaction(); 
   
  Customer customer3 = (Customer) session.get(Customer.class, 1);// 不发送SQL. 
  Customer customer4 = (Customer) session.get(Customer.class, 1);// 不发送SQL. 
   
  System.out.println(customer3 == customer4); 
   
  tx.commit(); 
 } 
  
  
 @SuppressWarnings("unused") 
 @Test 
 // 没有配置二级缓存的情况 
 public void demo1(){ 
  Session session = HibernateUtils.getCurrentSession(); 
  Transaction tx = session.beginTransaction(); 
   
  Customer customer1 = (Customer) session.get(Customer.class, 1);// 发送SQL. 
   
  Customer customer2 = (Customer) session.get(Customer.class, 1);// 不发送SQL. 
   
   
   
  tx.commit(); 
   
  session = HibernateUtils.getCurrentSession(); 
  tx = session.beginTransaction(); 
   
  Customer customer3 = (Customer) session.get(Customer.class, 1);// 发送SQL. 
   
   
  tx.commit(); 
 } 
} 

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。


推荐阅读
  • 在当前众多持久层框架中,MyBatis(前身为iBatis)凭借其轻量级、易用性和对SQL的直接支持,成为许多开发者的首选。本文将详细探讨MyBatis的核心概念、设计理念及其优势。 ... [详细]
  • 探讨如何真正掌握Java EE,包括所需技能、工具和实践经验。资深软件教学总监李刚分享了对毕业生简历中常见问题的看法,并提供了详尽的标准。 ... [详细]
  • 本文详细介绍如何使用Python进行配置文件的读写操作,涵盖常见的配置文件格式(如INI、JSON、TOML和YAML),并提供具体的代码示例。 ... [详细]
  • 本文详细介绍了Java编程语言中的核心概念和常见面试问题,包括集合类、数据结构、线程处理、Java虚拟机(JVM)、HTTP协议以及Git操作等方面的内容。通过深入分析每个主题,帮助读者更好地理解Java的关键特性和最佳实践。 ... [详细]
  • 将Web服务部署到Tomcat
    本文介绍了如何在JDeveloper 12c中创建一个Java项目,并将其打包为Web服务,然后部署到Tomcat服务器。内容涵盖从项目创建、编写Web服务代码、配置相关XML文件到最终的本地部署和验证。 ... [详细]
  • XNA 3.0 游戏编程:从 XML 文件加载数据
    本文介绍如何在 XNA 3.0 游戏项目中从 XML 文件加载数据。我们将探讨如何将 XML 数据序列化为二进制文件,并通过内容管道加载到游戏中。此外,还会涉及自定义类型读取器和写入器的实现。 ... [详细]
  • Android LED 数字字体的应用与实现
    本文介绍了一种适用于 Android 应用的 LED 数字字体(digital font),并详细描述了其在 UI 设计中的应用场景及其实现方法。这种字体常用于视频、广告倒计时等场景,能够增强视觉效果。 ... [详细]
  • RecyclerView初步学习(一)
    RecyclerView初步学习(一)ReCyclerView提供了一种插件式的编程模式,除了提供ViewHolder缓存模式,还可以自定义动画,分割符,布局样式,相比于传统的ListVi ... [详细]
  • 本文介绍如何在 Unity 的 XML 配置文件中,将参数传递给自定义生命周期管理器的构造函数。我们将详细探讨 CustomLifetimeManager 类的实现及其配置方法。 ... [详细]
  • 本文详细介绍了 Java 中 org.apache.xmlbeans.SchemaType 类的 getBaseEnumType() 方法,提供了多个代码示例,并解释了其在不同场景下的使用方法。 ... [详细]
  • 本文详细介绍了如何解决MyBatis中常见的BindingException错误,提供了多种排查和修复方法,确保Mapper接口与XML文件的正确配置。 ... [详细]
  • 基于KVM的SRIOV直通配置及性能测试
    SRIOV介绍、VF直通配置,以及包转发率性能测试小慢哥的原创文章,欢迎转载目录?1.SRIOV介绍?2.环境说明?3.开启SRIOV?4.生成VF?5.VF ... [详细]
  • 解决JAX-WS动态客户端工厂弃用问题并迁移到XFire
    在处理Java项目中的JAR包冲突时,我们遇到了JaxWsDynamicClientFactory被弃用的问题,并成功将其迁移到org.codehaus.xfire.client。本文详细介绍了这一过程及解决方案。 ... [详细]
  • 本文探讨了在通过 API 端点调用时,使用猫鼬(Mongoose)的 findOne 方法总是返回 null 的问题,并提供了详细的解决方案和建议。 ... [详细]
  • 本文介绍如何使用布局文件在Android应用中排列多行TextView和Button,使其占据屏幕的特定比例,并提供示例代码以帮助理解和实现。 ... [详细]
author-avatar
傅笑寒
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有