• Hibernate学习11——配置Hibernate二级缓存


    一、缓存的概念:                                                

    以空间换时间;
     
    二、Hibernate缓存的分类:                                        
    前面我们讲的缓存都是session缓存;也叫一级缓存;get,load等缓存都是内置的,一级缓存;
    SessionFactory缓存,二级缓存;

    这里以Class —— Student,1对多的关系(单向)来例子说明下:

    Class.java:

    package com.cy.model;
    
    public class Class {
        private int id;
        private String name;
        
        public int getId() {
            return id;
        }
        public void setId(int id) {
            this.id = id;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        
        
    }
    View Code

    Student.java:

    package com.cy.model;
    
    import com.cy.model.Class;
    
    public class Student {
        private int id;
        private String name;
        private Class c;
        
        public int getId() {
            return id;
        }
        public void setId(int id) {
            this.id = id;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public Class getC() {
            return c;
        }
        public void setC(Class c) {
            this.c = c;
        }
        
        
    }
    View Code

    Class.hbm.xml:

    <hibernate-mapping package="com.cy.model">
    
        <class name="Class" table="t_class">
            <id name="id" column="classId">
                <generator class="native"></generator>
            </id>
            <property name="name" column="className"></property>
        </class>
    
    </hibernate-mapping>
    View Code

    Student.hbm.xml:

    <hibernate-mapping package="com.cy.model">
    
        <class name="Student" table="t_student">
            <id name="id" column="stuId">
                <generator class="native"></generator>
            </id>
            <property name="name" column="stuName"></property>
            
            <many-to-one name="c" class="com.cy.model.Class" column="classId" cascade="save-update"></many-to-one>
        </class>
    
    </hibernate-mapping>
    View Code

    StudentTest.java:

    package com.cy.service;
    
    import org.hibernate.Session;
    import org.hibernate.SessionFactory;
    import org.junit.After;
    import org.junit.Before;
    import org.junit.Test;
    import com.cy.model.Class;
    import com.cy.util.HibernateUtil;
    
    public class StudentTest {
    
        private SessionFactory sessionFactory=HibernateUtil.getSessionFactory();
        private Session session;
        
        @Before
        public void setUp() throws Exception {
            session=sessionFactory.openSession(); 
            session.beginTransaction();
        }
    
        @After
        public void tearDown() throws Exception {
             session.getTransaction().commit();
             session.close();
        }
        
        /**
         * 同一个session中,同一个事务是有一级缓存的;
         */
        @Test
        public void testCache1(){
            Class c = (Class) session.get(Class.class, 1);
            System.out.println(c.getName());
            
            Class c2 = (Class) session.get(Class.class, 1);
            System.out.println(c2.getName());
            System.out.println(c == c2);
            
            /*
             *  Hibernate: select class0_.classId as classId1_0_0_, class0_.className as classNam2_0_0_ from t_class class0_ where class0_.classId=?
                08计算机本科
                08计算机本科
                true
                
                第一次取c1的时候,已经将取出来的数据c1放到缓存中。
                第二次取c2的时候,是有session缓存的。首选从缓存中找,找到,直接从缓存中拿,而不到数据库中去取了。
                两个是同一个OID对象;
             */
        }
        
        /**
         * 在不同的事务中,是否有缓存?
         */
        @Test
        public void testCache2(){
            Session session1 = sessionFactory.openSession();
            session1.beginTransaction();
            Class c = (Class) session1.get(Class.class, 1);
            System.out.println(c.getName());
            session1.getTransaction().commit();
            session1.close();
            
            
            Session session2 = sessionFactory.openSession();
            session2.beginTransaction();
            Class c2 = (Class) session2.get(Class.class, 1);
            System.out.println(c2.getName());
            session2.getTransaction().commit();
            session2.close();
            
            System.out.println(c == c2);
            /*
             *  Hibernate: select class0_.classId as classId1_0_0_, class0_.className as classNam2_0_0_ from t_class class0_ where class0_.classId=?
                08计算机本科
                Hibernate: select class0_.classId as classId1_0_0_, class0_.className as classNam2_0_0_ from t_class class0_ where class0_.classId=?
                08计算机本科
                false
                
                虽然在同一个session中有缓存,但是这里新开辟了一个事务,发出两个sql
                不同的事务是不能共用一级缓存的。
                一级缓存只适用于同一个session,同一个事务;
             */
        }
    }
    View Code

    三、二级缓存策略提供商:                                          

    配置ehcache二级缓存,让不同的session,不同的事务能共享数据。
    要用到SessionFactory缓存了;
     
    使用到的ehcache相关的jar包:

    jar包在hibernate压缩包中:
    hibernate-release-4.3.5.Finalliboptionalehcache
    可以参考hibernate压缩包中的hibernate-ehcache的配置:
    hibernate-release-4.3.5.Finalprojecthibernate-ehcachein
    hibernate-release-4.3.5.Finalprojecthibernate-ehcacheinhibernate-configehcache.xml 以及hibernate.cfg.xml
     
    代码实现:
    1)ehcache.xml配置:
    <ehcache>
       
           <!-- 指定一个文件目录,当EHCache把数据写到硬盘上时,将把数据写到这个目录下 -->
        <diskStore path="E:\ehcache"/>
        
        <!--  
            设置缓存的默认数据过期策略 
        -->    
        <defaultCache
            maxElementsInMemory="10000"
            eternal="false"
            timeToIdleSeconds="120"
            timeToLiveSeconds="120"
            overflowToDisk="true"
         />
    
        <!-- 
            name 设置缓存的名字,他的取值为类的完整名字或者类的集合的名字;
            maxElementsInMemory 设置基于内存的缓存可存放的对象的最大数目
            eternal 如果为true,表示对象永远不会过期,此时会忽略timeToIdleSeconds和timeToLiveSeconds,默认为false;
            timeToIdleSeconds 设定允许对象处于空闲状态的最长时间,以秒为单位;
            timeToLiveSeconds 设定对象允许存在于缓存中的最长时间,以秒为单位;
            overflowToDisk 如果为true,表示当基于内存的缓存中的对象数目达到maxElementsInMemory界限,会把溢出的对象写到基于硬盘的缓存中;
         -->
    
    
        <!-- 设定具体的第二级缓存的数据过期策略 -->
        <cache name="com.cy.model.Class"
            maxElementsInMemory="1"
            eternal="false"
            timeToIdleSeconds="300"
            timeToLiveSeconds="600"
            overflowToDisk="true"
         />
     
    
    </ehcache>
    View Code

    2)hibernate.cfg.xml中相关ehcache二级缓存的配置:

    <?xml version='1.0' encoding='utf-8'?>
    <!DOCTYPE hibernate-configuration PUBLIC
            "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
            "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
    
    <hibernate-configuration>
    
        <session-factory>
    
            <!--数据库连接设置 -->
            <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
            <property name="connection.url">jdbc:mysql://localhost:3306/hibernate</property>
            <property name="connection.username">root</property>
            <property name="connection.password">root</property>
           
            <!-- 方言 -->
            <property name="dialect">org.hibernate.dialect.MySQL5Dialect</property>
        
            <!-- 控制台显示SQL -->
            <property name="show_sql">true</property>
    
            <!-- 自动更新表结构 -->
            <property name="hbm2ddl.auto">update</property>
            
             <!-- 启用二级缓存 -->
            <property name="cache.use_second_level_cache">true</property>
            <!-- 配置使用的二级缓存的产品 -->
            <property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property>
            <!-- 配置启用查询缓存 -->
            <property name="cache.use_query_cache">true</property>
            <property name="net.sf.ehcache.configurationResourceName">ehcache.xml</property>
            
            <mapping resource="com/cy/model/Student.hbm.xml"/>
            <mapping resource="com/cy/model/Class.hbm.xml"/>
        </session-factory>
    
    </hibernate-configuration>

    3)最后,Class.hbm.xml中配置使用cache:

    <?xml version="1.0"?>
    <!DOCTYPE hibernate-mapping PUBLIC
            "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
            "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
    
    <hibernate-mapping package="com.cy.model">
    
        <class name="Class" table="t_class">
            <cache usage="read-only"/>
            <id name="id" column="classId">
                <generator class="native"></generator>
            </id>
            <property name="name" column="className"></property>
        </class>
    
    </hibernate-mapping>

    4)测试代码:

    /**
         * 配置了二级缓存ehcache后,再次进行测试:
         */
        @Test
        public void testCache3(){
            Session session1 = sessionFactory.openSession();
            session1.beginTransaction();
            Class c = (Class) session1.get(Class.class, 1);
            System.out.println(c.getName());
            session1.getTransaction().commit();
            session1.close();
            
            
            Session session2 = sessionFactory.openSession();
            session2.beginTransaction();
            Class c2 = (Class) session2.get(Class.class, 1);
            System.out.println(c2.getName());
            session2.getTransaction().commit();
            session2.close();
            
            System.out.println(c == c2);
            /*
             *  Hibernate: select class0_.classId as classId1_0_0_, class0_.className as classNam2_0_0_ from t_class class0_ where class0_.classId=?
                08计算机本科
                08计算机本科
                false
                
                只有1条sql,说明在第2次查的时候,使用到了二级缓存。
             */
            
        }
    View Code

    四、什么数据适合放二级缓存中                                    

    一般这些信息都是只读;不能修改;
     
     
     
  • 相关阅读:
    春秋宋国
    MySQL查询性能优化七种武器之索引下推
    HbuliderX H5前端部署+Nginx+docker20220912
    春秋秦国
    春秋郑国
    docker安装 iotdb
    springboot集成Spring Batch 20220902
    跨境电商
    江西两大文化巨头:抚州有叫板江西的底气,吉安有叫板全国的底气
    CDH搭建教程
  • 原文地址:https://www.cnblogs.com/tenWood/p/7259681.html
Copyright © 2020-2023  润新知