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


相关推荐: 在线教育网站制作平台,山西立德教育官网?  如何快速重置建站主机并恢复默认配置?  详解vue.js组件化开发实践  如何在 React 中条件性地遍历数组并渲染元素  如何在新浪SAE免费搭建个人博客?  香港服务器网站推广:SEO优化与外贸独立站搭建策略  Win11怎样安装网易有道词典_Win11安装词典教程【步骤】  北京的网站制作公司有哪些,哪个视频网站最好?  佛山企业网站制作公司有哪些,沟通100网上服务官网?  Laravel怎么导出Excel文件_Laravel Excel插件使用教程  Gemini手机端怎么发图片_Gemini手机端发图方法【步骤】  Python制作简易注册登录系统  Laravel的契約(Contracts)是什么_深入理解Laravel Contracts与依赖倒置  如何用搬瓦工VPS快速搭建个人网站?  黑客如何利用漏洞与弱口令入侵网站服务器?  厦门模型网站设计制作公司,厦门航空飞机模型掉色怎么办?  如何快速搭建二级域名独立网站?  Laravel如何使用Eloquent ORM进行数据库操作?(CRUD示例)  如何在阿里云虚拟机上搭建网站?步骤解析与避坑指南  如何快速登录WAP自助建站平台?  深圳网站制作的公司有哪些,dido官方网站?  Laravel策略(Policy)如何控制权限_Laravel Gates与Policies实现用户授权  Laravel怎么集成Log日志记录_Laravel单文件与每日日志配置及自定义通道【详解】  Laravel项目如何进行性能优化_Laravel应用性能分析与优化技巧大全  中山网站制作网页,中山新生登记系统登记流程?  ChatGPT 4.0官网入口地址 ChatGPT在线体验官网  Laravel怎么写单元测试_PHPUnit在Laravel项目中的基础测试入门  Laravel API资源(Resource)怎么用_格式化Laravel API响应的最佳实践  如何在建站之星网店版论坛获取技术支持?  微博html5版本怎么弄发语音微博_语音录制入口及时长限制操作【教程】  JavaScript如何实现错误处理_try...catch如何捕获异常?  Claude怎样写结构化提示词_Claude结构化提示词写法【教程】  Gemini怎么用新功能实时问答_Gemini实时问答使用【步骤】  网页制作模板网站推荐,网页设计海报之类的素材哪里好?  谷歌Google入口永久地址_Google搜索引擎官网首页永久入口  Linux系统命令中screen命令详解  如何在建站宝盒中设置产品搜索功能?  Laravel怎么配置不同环境的数据库_Laravel本地测试与生产环境动态切换【方法】  Laravel怎么做缓存_Laravel Cache系统提升应用速度的策略与技巧  如何在宝塔面板中修改默认建站目录?  Java Adapter 适配器模式(类适配器,对象适配器)优缺点对比  高端智能建站公司优选:品牌定制与SEO优化一站式服务  网站制作大概多少钱一个,做一个平台网站大概多少钱?  香港服务器选型指南:免备案配置与高效建站方案解析  如何基于PHP生成高效IDC网络公司建站源码?  如何用西部建站助手快速创建专业网站?  如何用花生壳三步快速搭建专属网站?  原生JS实现图片轮播切换效果  Laravel怎么设置路由分组Prefix_Laravel多级路由嵌套与命名空间隔离【步骤】  如何快速搭建虚拟主机网站?新手必看指南