java中hibernate二级缓存详解

发布时间 - 2026-01-11 01:00:29    点击率:

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 开启二级缓存

<property name="hibernate.cache.use_second_level_cache">true</property>

3 要指定缓存的供应商

 <property name="hibernate.cache.provider_class">
    org.hibernate.cache.EhCacheProvider</property>

4 指定使用二级缓存的类

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

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

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

  <!-- 指定使用二级缓存的类 放在maping下面 -->
  <!-- 配置类级别的二级缓存 -->
  <class-cache class="com.sihai.c3p0.Customer" usage="read-write"/>
  <class-cache class="com.sihai.c3p0.Order" usage="read-write"/>
 
  <!-- 配置集合级别的二级缓存 -->
  <collection-cache collection="com.sihai.c3p0.Customer.orders" 
         usage="read-write"/>

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

<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../config/ehcache.xsd"> 
 
 <diskStore path="c:/ehcache"/> 
 <defaultCache 
   maxElementsInMemory="5" 
   eternal="false" 
   timeToIdleSeconds="120" 
   timeToLiveSeconds="120" 
   overflowToDisk="true" 
   maxElementsOnDisk="10000000" 
   diskPersistent="false" 
   diskExpiryThreadIntervalSeconds="120" 
   memoryStoreEvictionPolicy="LRU" 
   /> 
</ehcache> 

四、 测试

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<Order> 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<Customer> 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<Customer> 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(); 
 } 
} 

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


# hibernate  # 二级缓存  # hibernate的二级缓存  # 详解Java的Hibernate框架中的缓存与二级缓存  # 详解Java的Hibernate框架中的缓存与原生SQL语句的使用  # 详解Java的Hibernate框架中的注解与缓存  # 浅析Java的Hibernate框架中的缓存和延迟加载机制  # java模拟hibernate一级缓存示例分享  # java中Hibernate缓存形式总结  # 外置  # 放在  # 它是  # 会向  # 应用程序  # 这一  # 更新时间  # 写到  # 会把  # 自带  # 两类  # 推到  # 配置文件  # 大家多多  # 可以分为  # 法会  # 情况下  # 目录下  # usage  # Customer 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: ,在苏州找工作,上哪个网站比较好?  浅述节点的创建及常见功能的实现  焦点电影公司作品,电影焦点结局是什么?  Laravel Pest测试框架怎么用_从PHPUnit转向Pest的Laravel测试教程  Win11怎么查看显卡温度 Win11任务管理器查看GPU温度【技巧】  如何用好域名打造高点击率的自主建站?  Laravel怎么返回JSON格式数据_Laravel API资源Response响应格式化【技巧】  Laravel如何配置Horizon来管理队列?(安装和使用)  如何在云主机快速搭建网站站点?  标准网站视频模板制作软件,现在有哪个网站的视频编辑素材最齐全的,背景音乐、音效等?  Laravel如何获取当前登录用户信息_Laravel Auth门面使用与Session用户读取【技巧】  Laravel如何自定义分页视图?(Pagination示例)  如何使用 Go 正则表达式精准提取括号内首个纯字母标识符(忽略数字与嵌套)  Laravel Blade组件怎么用_Laravel可复用视图组件的创建与使用  VIVO手机上del键无效OnKeyListener不响应的原因及解决方法  如何将凡科建站内容保存为本地文件?  网站制作报价单模板图片,小松挖机官方网站报价?  Claude怎样写结构化提示词_Claude结构化提示词写法【教程】  微信h5制作网站有哪些,免费微信H5页面制作工具?  黑客入侵网站服务器的常见手法有哪些?  Laravel如何从数据库删除数据_Laravel destroy和delete方法区别  微博html5版本怎么弄发语音微博_语音录制入口及时长限制操作【教程】  如何制作公司的网站链接,公司想做一个网站,一般需要花多少钱?  Laravel API路由如何设计_Laravel构建RESTful API的路由最佳实践  Laravel如何实现多对多模型关联?(Eloquent教程)  Android Socket接口实现即时通讯实例代码  Laravel如何实现全文搜索功能?(Scout和Algolia示例)  javascript和jQuery中的AJAX技术详解【包含AJAX各种跨域技术】  如何获取上海专业网站定制建站电话?  Laravel如何生成和使用数据填充?(Seeder和Factory示例)  QQ浏览器网页版登录入口 个人中心在线进入  Laravel如何使用查询构建器?(Query Builder高级用法)  如何在建站主机中优化服务器配置?  Laravel Vite是做什么的_Laravel前端资源打包工具Vite配置与使用  Laravel怎么实现搜索功能_Laravel使用Eloquent实现模糊查询与多条件搜索【实例】  Laravel如何自定义错误页面(404, 500)?(代码示例)  如何用PHP快速搭建高效网站?分步指南  Python正则表达式进阶教程_复杂匹配与分组替换解析  Laravel与Inertia.js怎么结合_使用Laravel和Inertia构建现代单页应用  Win10如何卸载预装Edge扩展_Win10卸载Edge扩展教程【方法】  Laravel Eloquent访问器与修改器是什么_Laravel Accessors & Mutators数据处理技巧  JavaScript中的标签模板是什么_它如何扩展字符串功能  手机软键盘弹出时影响布局的解决方法  Laravel事件监听器怎么写_Laravel Event和Listener使用教程  大连网站制作公司哪家好一点,大连买房网站哪个好?  Laravel怎么清理缓存_Laravel optimize clear命令详解  Python文件流缓冲机制_IO性能解析【教程】  Python自动化办公教程_ExcelWordPDF批量处理案例  齐河建站公司:营销型网站建设与SEO优化双核驱动策略  怎么用AI帮你为初创公司进行市场定位分析?