zoukankan      html  css  js  c++  java
  • 具体解释Hibernate中的二级缓存

      

     1.前言

    这篇博客再前几篇博客的基础上来解说一下。Hibernate中的二级缓存。二级缓存是属于SessionFactory级别的缓存机制。

    第一级别的缓存是Session级别的缓存,是属于事务范围的缓存,由Hibernate管理,一般无需进行干预。第二级别的缓存是SessionFactory级别的缓存。是属于进程范围的缓存。


     2.Hibernate二级缓存

    1.分类

    二级缓存也分为了两种

    内置缓存:Hibernate自带的,不可卸载,通常在Hibernate的初始化阶段,Hibernate会把映射元数据和提前定义的SQL语句放置到SessionFactory的缓存中。该内置缓存是仅仅读的。

    外置缓存:通常说的二级缓存也就是外置缓存,在默认情况下SessionFactory不会启用这个缓存插件,外置缓存中的数据是数据库数据的复制,外置缓存的物理介质能够是内存或者硬盘。

    hibernate二级缓存的结构





    2.并发訪问策略

    transactional

    (事务型)

    仅在受管理的环境中适用

    提供Repeatable Read事务隔离级别

    适用常常被读。非常少改动的数据

    能够防止脏读和不可反复读的并发问题

    缓存支持事务,发生异常的时候。缓存也可以回滚

    read-write

    (读写型)

    提供Read Committed事务隔离级别

    在非集群的环境中适用

    适用常常被读,非常少改动的数据

    能够防止脏读

    更新缓存的时候会锁定缓存中的数据

    nonstrict-read-write

    (非严格读写型)

    适用极少被改动,偶尔同意脏读的数据(两个事务同一时候改动数据的情况非常少见)

    不保证缓存和数据库中数据的一致性

    为缓存数据设置非常短的过期时间,从而尽量避免脏读

    不锁定缓存中的数据

    read-only

    (仅仅读型)

    适用从来不会被改动的数据(如參考数据)

    在此模式下,假设对数据进行更新操作,会有异常

    事务隔离级别低,并发性能高

    在集群环境中也能完美运作


    分析:通过上述表格分析例如以下

    适合放入二级缓存中数据

    非常少被改动

    不是非常重要的数据。同意出现偶尔的并发问题

    不适合放入二级缓存中的数据

    常常被改动

    財务数据,绝对不同意出现并发问题

    与其它应用数据共享的数据


     3.二级缓存的配置

    1.hibernate支持的缓存插件

    EHCache: 可作为进程范围内的缓存,存放数据的物理介质能够是内存或硬盘,对Hibernate的查询缓存提供了支持

    OpenSymphony`:可作为进程范围内的缓存,存放数据的物理介质能够是内存或硬盘,提供了丰富的缓存数据过期策略,对Hibernate的查询缓存提供了支持

    SwarmCache:可作为集群范围内的缓存,但不支持Hibernate的查询缓存

    JBossCache:可作为集群范围内的缓存,支持Hibernate的查询缓存


    四种缓存插件支持的并发范围策略例如以下图




    2.二级缓存配置

    以下以ehcache缓存为例,来讲一下二级缓存的配置

    2.1 拷贝jar包

    如要第三方的jar包ehcache-1.5.0.jar,而且依赖于

    依赖backport-util-concurrent 和 commons-logging

    2.2 在hibernate.cfg.xml中开启二级缓存

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

    2.3 配置二级缓存技术提供商

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

    2.4 配置缓存数据对象并发策略

    方式一 在hbm文件里配置

    <span style="font-family:SimSun;font-size:18px;"><class name="cn.itcast.domain.Customer" table="customers" catalog="hibernate3day4" >
    				<!-- 类级别缓存 -->
    				<cache usage="read-write"/>
    				<set name="orders" cascade="all-delete-orphan" inverse="true" >
    					<!-- 关联集合级别缓存 -->
    					<cache usage="read-write"/>	
    				</set>
    			</class>
    </span>


    方式二 在cfg文件配置(集中配置)


    <span style="font-family:SimSun;font-size:18px;"><!-- 类级别缓存 -->
    			<class-cache usage="read-write" class="cn.itcast.domain.Customer"/>
    			<class-cache usage="read-write" class="cn.itcast.domain.Order"/>
    			<!-- 集合缓存 -->
    			<collection-cache usage="read-write" collection="cn.itcast.domain.Customer.orders"/>
    </span>

    2.5 加入二级缓存配置文件

    在src中配置ehcache.xml,将ehcache.jar包中的ehcache-failsafe.xml 改名 ehcache.xml 放入 src 

    <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
    
        <diskStore path="java.io.tmpdir"/> 配置二级缓存硬盘暂时文件夹位置 
    		 <defaultCache  
                maxElementsInMemory="10000" // 内存中最大对象数量 ,超过数量。数据会被缓存到硬盘 
                eternal="false"
                timeToIdleSeconds="120" // 是否缓存为永久性 false 不永久
                timeToLiveSeconds="120" // 存活时间。对象无论是否使用,到了时间回收
                overflowToDisk="true" // 能否够缓存到硬盘
                maxElementsOnDisk="10000000" // 硬盘缓存最大对象数量 
                // 当jvm结束时是否持久化对象 true false 默认是false
                diskExpiryThreadIntervalSeconds="120"  // 指定专门用于清除过期对象的监听线程的轮询时间 
                memoryStoreEvictionPolicy="LRU" 
    
                />
    
    </ehcache>
    



     4.Demo測试二级缓存

    @Test
    	public void fun1() {
    
    		Session s1 = HibernateUtils.getSession();
    		s1.beginTransaction();
    		Customer c1 = (Customer) s1.get(Customer.class, 1); // 从数据库中载入数据
    		System.out.println(c1.getName());//此时才会发出SQL语句
    		s1.getTransaction().commit();
    		s1.close(); // 关闭session级别的一级缓存
    
    		Session s2 = HibernateUtils.getSession();
    		s2.beginTransaction();
    		Customer c2 = (Customer) s2.get(Customer.class, 1); // 由于有了二级缓存的存在,直接从二级缓存中取出就可以
    		System.out.println(c2.getName());
    
    		Customer c3 = (Customer) s2.get(Customer.class, 1); //从二级缓存中取出
    		System.out.println(c3.getName());
    
    		s2.getTransaction().commit();
    		s2.close();
    
    	}



  • 相关阅读:
    ExtJs之表格控件入门
    bootstrap错误警告信息提示
    android采用MVP漫画APP、适配刘海屏、小黄车主界面、录音波浪动画、综合APP等源码
    iOS仿QQ侧滑菜单、登录按钮动画、仿斗鱼直播APP、城市选择器、自动布局等源码
    iOS仿抖音节拍界面、Swift,MVVM架构完整项目、日历demo、滚动切换分类等源码
    接住! 安卓巴士开发者大会花絮第二弹来啦
    iOS漂亮的Toolbar动画、仿美团主页、简易笔记本、流失布局、标签分组等源码
    android仿今日头条App、多种漂亮加载效果、选择器汇总、记事本App、Kotlin开发等源码
    到场率高达96% 这才是高水准技术大会应该有的样子
    iOS动画效果集合、 通过摄像头获取心率、仿淘宝滑动样式、瀑布流、分类切换布局等源码
  • 原文地址:https://www.cnblogs.com/yutingliuyl/p/7028627.html
Copyright © 2011-2022 走看看