java中hibernate二级缓存详解

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

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

(0)

相关推荐

  • SSH框架网上商城项目第16战之Hibernate二级缓存处理首页热门显示

    网上商城首页都有热门商品,那么这些商品的点击率是很高的,当用户点击某个热门商品后需要进入商品的详细信息页面,就像淘宝里面那样.那么每次点击都要去后台查询一下该商品的详细信息,就会发送相应的sql语句,每次刷新一下详细页面也会发sql语句,这样的话,性能肯定会受到很大的影响.那么使用Hibernate的二级缓存就可以解决这个问题. 有些人可能会想,我们可以使用重定向,这样的话,在用户第一次访问的时候把信息查出来放到session中,以后每次用户刷新就可以去session中拿了,这样就不用去数据库中

  • JSP 开发之hibernate配置二级缓存的方法

    JSP 开发之hibernate配置二级缓存的方法 hibernate二级缓存也称为进程级的缓存或SessionFactory级的缓存. 二级缓存是全局缓存,它可以被所有的session共享. 二级缓存的生命周期和SessionFactory的生命周期一致,SessionFactory可以管理二级缓存. 常用的缓存插件 Hibernater二级缓存是一个插件,下面是几种常用的缓存插件: EhCache:可作为进程范围的缓存,存放数据的物理介质可以是内存或硬盘,对Hibernate的查询缓存提供了

  • 详解Java的Hibernate框架中的缓存与二级缓存

    缓存 今天我们就来讲一下hibernate中实体状态和hibernate缓存.  1)首先我们先来看一下实体状态:  实体状态主要分三种:transient,persitent,detached.  看英文应该就大概明白了吧.  transient:是指数据还没跟数据库中的数据相对应.  persistent:是指数据跟数据库中的数据相对应,它的任何改变都会反映到数据库中.  detached:是指数据跟数据库中的数据相对应,但由于session被关闭,它所做的修改不会对数据库的记录造成影响.

  • Spring 整合 Hibernate 时启用二级缓存实例详解

    Spring 整合 Hibernate 时启用二级缓存实例详解 写在前面: 1. 本例使用 Hibernate3 + Spring3: 2. 本例的查询使用了 HibernateTemplate: 1. 导入 ehcache-x.x.x.jar 包: 2. 在 applicationContext.xml 文件中找到 sessionFactory 相应的配置信息并在设置 hibernateProperties 中添加如下代码: <!-- 配置使用查询缓存 --> <prop key=&q

  • 详解Hibernate注解方式的二级缓存

    详解Hibernate注解方式的二级缓存 hibernate默认情况下是支持一级缓存,也就是session级的缓存的,而默认情况下是不支持二级缓存,即sessionFactory级的缓存的,二级缓存        一般比较少去考虑它,除非对效率要求非常高的时候, 这时侯如果我们的某一个实体要在多个session里面使用需要用到session间的缓存的时候就可以进行配置来实现二级缓存了! 在看文档的时候说可以在persistence.xml里面进行配置,但我一般是不用这个文件的,就直接使用注解!

  • 详解spring boot集成ehcache 2.x 用于hibernate二级缓存

    本文将介绍如何在spring boot中集成ehcache作为hibernate的二级缓存.各个框架版本如下 spring boot:1.4.3.RELEASE spring framework: 4.3.5.RELEASE hibernate:5.0.1.Final(spring-boot-starter-data-jpa默认依赖) ehcache:2.10.3 项目依赖 <dependency> <groupId>org.springframework.boot</gro

  • java中hibernate二级缓存详解

    Hibernate的二级缓存 一.缓存概述 缓存(Cache): 计算机领域非常通用的概念.它介于应用程序和永久性数据存储源(如硬盘上的文件或者数据库)之间,其作用是降低应用程序直接读写永久性数据存储源的频率,从而提高应用的运行性能.缓存中的数据是数据存储源中数据的拷贝.缓存的物理介质通常是内存 hibernate中提供了两个级别的缓存 第一级别的缓存是 Session 级别的缓存,它是属于事务范围的缓存.这一级别的缓存由 hibernate 管理的,一般情况下无需进行干预 第二级别的缓存是 S

  • MyBatis 延迟加载、一级缓存、二级缓存(详解)

    使用ORM框架我们更多的是使用其查询功能,那么查询海量数据则又离不开性能,那么这篇中我们就看下mybatis高级应用之延迟加载.一级缓存.二级缓存.使用时需要注意延迟加载必须使用resultMap,resultType不具有延迟加载功能. 一.延迟加载 延迟加载已经是老生常谈的问题,什么最大化利用数据库性能之类之类的,也懒的列举了,总是我一提到延迟加载脑子里就会想起来了Hibernate get和load的区别.OK,废话少说,直接看代码. 先来修改配置项xml. 注意,编写mybatis.xm

  • 浅谈JAVA中输入输出流实例详解

    java语言的输入输出功能是十分强大而灵活的,美中不足的是看上去输入输出的代码并不是很简洁,因为你往往需要包装许多不同的对象.在Java类库中,IO部分的内容是很庞大的,因为它涉及的领域很广泛:标准输入输出,文件的操作,网络上的数据流,字符串流,对象流,zip文件流....本文的目的是为大家介绍JAVA中输入输出流实例详解. 流的层次结构 定义:        java将读取数据对象成为输入流,能向其写入的对象叫输出流.结构图如下: 1.输入输出: 输入/输出(Input/Output)是指对某

  • Java中文件管理系统FastDFS详解

    什么是FastDFS 很多以文件为载体的在线服务,如相册网站.视频网站等,都需要对文件进行管理,包括文件的存储.同步.访问(文件上传.文件下载)等,同时肯定会伴随着大容量存储和负载均衡的问题. 在日常的一些项目中,比如做用户的KYC认证等,也需要存储文件.图片.视频等.此时可以选择使用OSS云服务,也可以自己构建相对专业的文件管理系统. FastDFS是一个开源的轻量级分布式文件系统,用于解决大数据量存储和负载均衡等问题,并需要通过专有API进行访问.满足大容量文件存储问题,并保证高性能和高扩展

  • Java中浅拷贝和深拷贝详解

    目录 Java浅拷贝深拷贝 实现浅拷贝 实现深拷贝 Java浅拷贝深拷贝 浅拷贝和深拷贝涉及到了Object类中的clone()方法 实现浅拷贝 浅拷贝的实现需要类重写clone()方法 浅拷贝会创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝 如果属性是基本类型,拷贝的就是基本类型的值: 如果属性是内存地址(引用类型),拷贝的就是内存地址 ,因此如果其中一个对象改变了这个地址,就会影响到另一个对象,导致两个对象的引用不等. 实现浅拷贝很简单只需要将类实现Cloneable接口然后重写c

  • Java中自动生成构造方法详解

    Java中自动生成构造方法详解 每个类在没有声明构造方法的前提下,会自动生成一个不带参数的构造方法,如果类一但声明有构造方法,就不会产生了.证明如下: 例1: class person { person(){System.out.println("父类-person");} person(int z){} } class student extends person { // student(int x ,int y){super(8);} } class Rt { public st

  • 基于Java中的StringTokenizer类详解(推荐)

    StringTokenizer是字符串分隔解析类型,属于:Java.util包. 1.StringTokenizer的构造函数 StringTokenizer(String str):构造一个用来解析str的StringTokenizer对象.java默认的分隔符是"空格"."制表符('\t')"."换行符('\n')"."回车符('\r')". StringTokenizer(String str,String delim)

  • JAVA中string数据类型转换详解

    在JAVA中string是final类,提供字符串不可以修改,string类型在项目中经常使用,下面给大家介绍比较常用的string数据类型转换: String数据类型转换成long.int.double.float.boolean.char等七种数据类型 复制代码 代码如下: * 数据类型转换 * @author Administrator * */ public class 数据类型转换 { public static void main(String[] args) { String c=

  • java 中 阻塞队列BlockingQueue详解及实例

    java 中 阻塞队列BlockingQueue详解及实例 BlockingQueue很好的解决了多线程中数据的传输,首先BlockingQueue是一个接口,它大致有四个实现类,这是一个很特殊的队列,如果BlockQueue是空的,从BlockingQueue取东西的操作将会被阻断进入等待状态,直到BlockingQueue进了东西才会被唤醒.同样,如果BlockingQueue是满的,任何试图往里存东西的操作也会被阻断进入等待状态,直到BlockingQueue里有空间才会被唤醒继续操作.

  • Java中BigDecimal的基本运算(详解)

    BigDecimal一共有4个够造方法,让来看看其中比较常用的两种用法: 第一种:BigDecimal(double val) Translates a double into a BigDecimal. 第二种:BigDecimal(String val) Translates the String repre sentation of a BigDecimal into a BigDecimal. 使用BigDecimal要用String来够造,要做一个加法运算,需要先将两个浮点数转为Str

随机推荐