• Hibernate缓存


    Hibernate是一个持久层框架,经常访问物理数据库。

    为了降低应用程序对物理数据源访问的频次,从而提高应用程序的运行性能。

    缓存内的数据是对物理数据源中的数据的复制,应用程序在运行时从缓存读写数据,在特定的时刻或事件会同步缓存和物理数据源的数据。

    Hibernate缓存包括两大类:Hibernate一级缓存和Hibernate二级缓存。

    一.Hibernate一级缓存又称为“Session的缓存”。

    Session内置不能被卸载,Session的缓存是事务范围的缓存(Session对象的生命周期通常对应一个数据库事务或者一个应用事务)。

    一级缓存中,持久化类的每个实例都具有唯一的OID。

    1.使用 load和get加载对象的时候,会自动加载到缓存,读取的也会读缓存。

        public void testF(){
            Session session=null;
            try{
                session=HibernateUtil.getSession();
                //两个对象Hql查询语句是一样
                Info data1=session.get(Info.class, "p003");
                Info data2 =session.get(Info.class, "p003");
                //两个对象也是一样的
                System.out.println(data1 == data2);
                
            }
            catch (Exception e) {
                e.printStackTrace();
            }
            finally {
                HibernateUtil.closeSession();
            }
        }

    输出结果中只包含了一条 SQL语句,结果是true说明两个取出来的对象是同一个对象

    其原理是:第一次调用get()方法, Hibernate先检索缓存中是否有该查找对象,发现没有,Hibernate发送SELECT语句到数据库中取出相应的对象,然后将该对象放入缓存中,以便下次使用,第二次调用get()方法,Hibernate先检索缓存中是否有该查找对象,发现正好有该查找对象,就从缓存中取出来,不再去数据库中检索。

    2.使用hql查询多条数据库,如果使用getResultList()默认是无法放到缓存中的。

    public void testF(){
            Session session=null;
            try{
                session=HibernateUtil.getSession();
                //默认是无法放到缓存中的
                List<Info> list1 = session.createQuery("from Info").getResultList();
                List<Info> list2= session.createQuery("from Info").getResultList();
        
                System.out.println(list1 == list2);
            }
            catch (Exception e) {
                e.printStackTrace();
            }
            finally {
                HibernateUtil.closeSession();
            }
        }

    输出结果中包含了两天条 SQL语句,结果是false说明不是同一个对象,也没有用到缓存。

    但使用iterator()可以用在缓存中。

    @Test
        public void testF(){
            Session session=null;
            try{
                session=HibernateUtil.getSession();
           //iterator()迭代器
                Iterator<Info> list1=session.createQuery("from Info").iterate();
                while(list1.hasNext()){
                    System.out.println(list1.next().getName());
                }
                Iterator<Info> list2 = session.createQuery("from Info").iterate();
                while(list2.hasNext()){
                    System.out.println(list2.next().getName());
                }
            }
            catch (Exception e) {
                e.printStackTrace();
            }
            finally {
                HibernateUtil.closeSession();
            }
        }

      只有第一遍有语句,查第二遍的时候并不会在成语句,而是直接从缓存中取出

    二.Hibernate二级缓存又称为“SessionFactory的缓存”。

    由于SessionFactory对象的生命周期和应用程序的整个过程对应,Session关了后,只要SessionFactory没有close,还可以使用缓存,因此Hibernate二级缓存是进程范围或者集群范围的缓存,有可能出现并发问题,因此需要采用适当的并发访问策略,该策略为被缓存的数据提供了事务隔离级别。

    默认不带二缓存。需要使用第三方插件。SessionFactory级别的缓存 EhCache

    1.导入3个jar包

    2.在hibernate.cfg.xml中配置,启动二级缓存

    <property name="hibernate.cache.use_second_level_cache">true</property>
    <property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property>

    <?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="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
            <property name="hibernate.connection.url">jdbc:mysql://127.0.0.1:3306/mydb</property>
            <property name="hibernate.connection.username">root</property>
            <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
            <property name="show_sql">true</property>
            
            <!-- 启动二级缓存 -->
            <property name="hibernate.cache.use_second_level_cache">true</property>
            <property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property>
           <!-- <property name="hibernate.cache.use_query_cache">true</property> --><!-- 缓存查询语句,相同的查询语句就不再去查第二遍,但对象没有缓存 -->
          
            <mapping resource="com/itnba/maya/model/Family.hbm.xml"/>
            <mapping resource="com/itnba/maya/model/Info.hbm.xml"/>
            <mapping resource="com/itnba/maya/model/Nation.hbm.xml"/>
            <mapping resource="com/itnba/maya/model/Title.hbm.xml"/>
            <mapping resource="com/itnba/maya/model/Work.hbm.xml"/>
           
            
        </session-factory>
    </hibernate-configuration>

    3.把ehcache配置文件复制过来,在project的etc文件夹中。


    4.在实体对象的映射文件中的<class>下配置缓存。
    <cache usage="read-write"/>这句话放在<class>下的第一句

    <?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">
    <!-- Generated 2017-3-11 10:12:32 by Hibernate Tools 5.2.0.CR1 -->
    <hibernate-mapping>
        <class name="com.itnba.maya.model.Info" table="info" catalog="mydb" optimistic-lock="version">
            <cache usage="read-only"/> 
            <id name="code" type="string">
                <column name="Code" length="50" />
                <generator class="assigned" />
            </id>
            <many-to-one name="nation" class="com.itnba.maya.model.Nation" fetch="select">
                <column name="Nation" length="50" />
            </many-to-one>
            <property name="name" type="string">
                <column name="Name" length="50" />
            </property>
            <property name="sex" type="java.lang.Boolean">
                <column name="Sex" />
            </property>
            <property name="birthday" type="timestamp">
                <column name="Birthday" length="19" />
            </property>
        </class>
    </hibernate-mapping>

    5.如果使用load或get的时候,不需要其它操作,直接使用的二缓存,中间session关闭也没关系

        @Test
        public void testF2(){
            Session session=null;
            try{
                session=HibernateUtil.getSession();
                Info data1=session.get(Info.class, "p003");
                HibernateUtil.closeSession();//关闭session
                session=HibernateUtil.getSession();//重新打开session
                Info data2=session.get(Info.class, "p003");
                System.out.println(data1 == data2);
            }
            catch (Exception e) {
                e.printStackTrace();
            }
            finally {
                HibernateUtil.closeSession();
            }
        }

  • 相关阅读:
    spring的@Transactional注解详细用法
    解决:No qualifying bean of type [org.springframework.jdbc.core.JdbcTemplate] found for dependency
    SpringBoot2 启动报错 Failed to auto-configure a DataSource
    SpringBoot2 全局异常处理
    Intellij IDEA 将工程转换成maven工程 详解
    js性能优化
    JDK故障处理工具箱
    编写高性能的jquery代码
    maven工程解决jar包冲突依赖问题
    spring aop中xml配置文件中标签和属性对应的类
  • 原文地址:https://www.cnblogs.com/hq233/p/6535269.html
Copyright © 2020-2023  润新知