• 男子农田挖到古董抠出吓得魂飞魄散 2019-03-17
  • 瑞典南部城市发生枪击案致5人伤 警方:与恐袭无关 2019-03-10
  • 西安幼升小入学难问题出在哪儿教育部门将统筹协调安排 2019-03-10
  • 传统强队集体慢热(世界杯纵横) 2019-03-10
  • 乌鲁木齐水磨沟区开建两座立体停车库 2019-03-10
  • 山西新闻网特约摄影师名单&山西视觉志 2019-02-05
  • 广州旅游为何爆发出强大且持续的吸引力 2019-02-05
  • 今天看啥
      热点:

        北京赛车pk10历史记录 www.zwahn.com

        hibernate缓存的学习,hibernate缓存学习


        这篇博客将学习hibernate的缓存策略,缓存是hibernate提高性能的主要方法。
        在hibernate中缓存主要分为:session的缓存,sessionFactory的缓存,其中,sessionFactory缓存又分为:内置缓存和外置缓存,关于缓存有一下几点需要说明:
        1.session的缓存和sessionFactory的内置缓存,都是内置的,成为hibernate的一级缓存。
        2.sessionFactory的内置缓存中包含了映射元数据的预定义sql。
        3.sessionFactory的外置缓存是一个可以配置的插件。默认是不开启的,需要我们手动配置,外置缓存的数据是数据库数据的拷贝,外置缓存的存放地方可以是内存或者硬盘。

        内置缓存

        内置缓存是不能取消的,均由session来管理
        session缓存:缓存普通的属性
        sessionFactory缓存:缓存对象类型的数据
        当session关闭的时候,sessionFactory中缓存的对象将被清空。

        外置缓存

        外置缓存也叫二级缓存,是可以配置的,二级缓存缓存的是实体对象。

        一级缓存测试

        1.get方法测试

        UserInfo userInfo =  (UserInfo) session.get(UserInfo.class,10);
        System.out.println(userInfo.getUserName());
        System.out.println(userInfo.getUserName());
        System.out.println(userInfo.getUserName());
        System.out.println(userInfo.getUserName());
        System.out.println(userInfo.getUserName());

        这里我们获得id=10的userinfo对象,然后连续四次得到该对象的username属性,sql语句打印如下:
        这里写图片描述
        可以发现只有hibernate只发出了一条sql查询语句。
        2.load方法测试
        如果我们将上面通过get方法得到的实体类对象,改为load方法来加载,同样的,hibernate会只发出一条查询语句。
        3.list方法测试

        Session session = factory.openSession();
        String hql = "from UserInfo";
        List<UserInfo>lists = session.createQuery(hql).list();
        
        UserInfo userInfo =  (UserInfo) session.load(UserInfo.class,10);
        System.out.println(userInfo.getUserName());
        UserInfo userInfo2 =  (UserInfo) session.load(UserInfo.class,10);
        System.out.println(userInfo2.getUserName());
        System.out.println(userInfo.getUserName());
        System.out.println(userInfo.getUserName());
        System.out.println(userInfo.getUserName());

        此时hibernate同样只发出一条sql语句。
        这里写图片描述
        可以发现,首先查询所有数据,然后将其缓存到session中,再次查询的时候,不需要在从数据库当中查询。

        为什么数据会缓存到session中

        为什么hibernate查询出来的数据会缓存到session当中,我们先来看个例子:

        Session session = factory.openSession();
        String hql = "from UserInfo";
        List<UserInfo>lists = session.createQuery(hql).list();
        session.close();
        session = factory.openSession();
        UserInfo userInfo =  (UserInfo) session.load(UserInfo.class,10);
        System.out.println(userInfo.getUserName());
        UserInfo userInfo2 =  (UserInfo) session.load(UserInfo.class,10);
        System.out.println(userInfo2.getUserName());
        System.out.println(userInfo.getUserName());
        System.out.println(userInfo.getUserName());
        System.out.println(userInfo.getUserName());

        这里我只是在查询完成所有数据以后,增加了一条关闭session的语句。此时当再次load方法查询的时候,又会重新发出一条sql语句。这充分说明查询出的数据是缓存到session当中的。
        这里写图片描述

        session不能从缓存中取数据

        Session session = factory.openSession();
        String hql = "from UserInfo";
        List<UserInfo>lists = session.createQuery(hql).list();
        for (UserInfo userInfo : lists) {
            System.out.println(userInfo.getUserName());
        }
        List<UserInfo>lists2 = session.createQuery(hql).list();
        for (UserInfo userInfo : lists2) {
            System.out.println(userInfo.getUserName());
        }

        这里我两次通过list方法查询数据。hibernate发出的sql如下:
        这里写图片描述
        可以看出。list只能给缓存中存放数据,但是再次查询的时候还是会发出sql查询所有的语句。

        iterator查询

        刚才说了,list是只能给缓存中存放数据,但是却不能从缓存当中取数据。iterator是可以的,那么iterator是怎么做到的呢??看下面的代码:

        String hql = "from UserInfo";
        Iterator<UserInfo>itertor = session.createQuery(hql).iterate();
        while (itertor.hasNext()) {
                    System.out.println(itertor.next().getUserName());
        }
        
        Iterator<UserInfo>itertor2 = session.createQuery(hql).iterate();
        while (itertor2.hasNext()) {
                    System.out.println(itertor2.next().getUserName());
        }

        这里两次通过iterator查询所有的数据,此时hibernate发出的sql语句如下图:
        这里写图片描述

        list和iterator结合使用

        我们现在已经知道了,list是可以给缓存当中存放数据的,可是不可以从缓存当中取数据,list查询只发出一条sql查询所有的语句即可,而iterator是可以从缓存当中读取数据的,如果使用iterator查询所有数据,会首先查询所有的id,然后根据id一次发出sql语句,查询每一条记录,这样无形当中就降低了查询效率,那么我们可以根据这些特性,将list查询和iterator查询结合起来使用。
        我们可以首先使用list查询所有,这样只会发出一条查询语句,不必想iterator那样发出n+1条sql语句,提升了查询效率,第一次之后查询所有数据的时候,就可以直接使用iterator来查询,这样可以只查询所有的id,然后根据id从缓存当中取数据,代码如下:

        String hql = "from UserInfo";
        List<UserInfo>lists = session.createQuery(hql).list();
        for (UserInfo userInfo : lists) {
            System.out.println(userInfo.getUserName());
        }
        Iterator<UserInfo>itertor = session.createQuery(hql).iterate();
        while (itertor.hasNext()) {
                    System.out.println(itertor.next().getUserName());
        }

        此时hibernate发出的sql和我们预期的一样:
        这里写图片描述

        hibernate二级缓存

        在hibernate中,二级缓存默认是打开的,一般来讲,hibernate的二级缓存是和应用的生命周期是一样的,由于二级缓存的数据每一个session都可以进行访问和更改,所以如果出现高并发的时候,有可能会出现问题。
        1.添加ecache所需的jar文件:
        在hibernate-release-4.3.10.Final\lib\optional\ehcache目录下有这样三个jar文件,需要加入到工程中:
        slf4j-api-1.6.1.jar
        hibernate-ehcache-4.3.10.Final.jar
        ehcache-core-2.4.3.jar
        2.配置二级缓存:
        在hibernate.cfg.xml文件中进行配置:

        <!-- 配置缓存提供类 -->
        <property name="cache.provider_class">
            org.hibernate.cache.EhCacheProvider
        </property>
        <!-- 启用查询缓存 -->
        <property name="cache.use_query_cache">true</property>

        所谓查询缓存就是让hibernate缓存list,iterator,createQuery等方法的查询结果集,如果没有打开查询缓存,hibernate将只缓存load方法获得的单个持久化对象。
        注意:在打开查询缓存 之后,调用query.list()之前,必须显示调用query.setCacheable(true)来标识该查询使用缓存。
        3.建立ehcache.xml,在类路径下:

        <?xml version="1.0" encoding="UTF-8"?>
        <ehcache>  
            <diskStore path="java.io.tmpdir"/>  
            <defaultCache
                maxElementsInMemory="10000"
                eternal="false"
                timeToIdleSeconds="120"
                timeToLiveSeconds="120"
                overflowToDisk="true"
                maxElementsOnDisk="10000000"
                diskPersistent="false"
                diskExpiryThreadIntervalSeconds="120"
                memoryStoreEvictionPolicy="LRU"
                />
        </ehcache>
        

        说明一下:
        diskStore表示设置cache文件的存放目录,有如下三种配置:
        1.user.home 表示用户的主目录
        2.user.home 表示用户当前的工作目录
        3.java.io.tmpdir 默认的temp文件目录
        maxElementsInMemory :在内存中最大的对象缓存数量
        eternal :设置是否为永久缓存,如果是永久缓存,则timeout将被忽略。
        可选的属性:
        timeToIdleSeconds:表示设置元素过期前的空闲时间
        timeToLiveSeconds:表示设置元素过期前的活动时间
        diskPersistent:表示是否disk store在虚拟机启动时持久化。默认为false
        diskExpiryThreadIntervalSeconds:表示运行disk终结线程的时间,默认为120秒
        memoryStoreEvictionPolicy:表示策略关于Eviction
        4.配置映射文件
        在需要被缓存的类对应的映射文件中配置hibernate的缓存策略

        <cache usage="read-write"/><!--  配置hibernate缓存策略 -->

        这里我配置的缓存策略是可读写的。该配置有如下一些值:
        1.read-only :表示无需修改的数据。
        2.read-write :需要更新数据
        3.nonstrict-read-write 非严格读写缓存策略。只需要偶尔更新数据,并且也不需要十分严格的事物隔离。
        5.编写测试代码:

        Query query = session.createQuery("from UserInfo");
        query.setCacheable(true)
        List<UserInfo> list = query.list();
        for (UserInfo userinfo : list) {
            System.out.println(userinfo.getUid()+"---"+userinfo.getUname());
        }
        session.close();
        Session session2 = sf.openSession();
        UserInfo userinfo =(UserInfo)session2.get(UserInfo.class, 1);       System.out.println(userinfo.getUid()+"***"+userinfo.getUname());

        这里,虽然第一次查询完成后session就已经关闭,但是由于配置了二级缓存,所以当session2再次查询的时候,是不需要再发出sql语句从数据库当中查询的。

        关于hibernate的缓存的学习就到这里了。

        北京赛车pk10历史记录 www.zwahn.comtrue//www.zwahn.com/sybase/1236553.htmlTechArticlehibernate缓存的学习,hibernate缓存学习 这篇博客将学习hibernate的缓存策略,缓存是hibernate提高性能的主要方法。 在hibernate中缓存主要分为:...

        相关文章

        相关搜索: 缓存

        帮客评论

        视觉看点
      • 男子农田挖到古董抠出吓得魂飞魄散 2019-03-17
      • 瑞典南部城市发生枪击案致5人伤 警方:与恐袭无关 2019-03-10
      • 西安幼升小入学难问题出在哪儿教育部门将统筹协调安排 2019-03-10
      • 传统强队集体慢热(世界杯纵横) 2019-03-10
      • 乌鲁木齐水磨沟区开建两座立体停车库 2019-03-10
      • 山西新闻网特约摄影师名单&山西视觉志 2019-02-05
      • 广州旅游为何爆发出强大且持续的吸引力 2019-02-05