• 【SSH网上商城项目实战16】Hibernate的二级缓存处理首页的热门显示


    转自:https://blog.csdn.net/eson_15/article/details/51405911    

    网上商城首页都有热门商品,那么这些商品的点击率是很高的,当用户点击某个热门商品后需要进入商品的详细信息页面,就像淘宝里面那样。那么每次点击都要去后台查询一下该商品的详细信息,就会发送相应的sql语句,每次刷新一下详细页面也会发sql语句,这样的话,性能肯定会受到很大的影响。那么使用Hibernate的二级缓存就可以解决这个问题。

            有些人可能会想,我们可以使用重定向,这样的话,在用户第一次访问的时候把信息查出来放到session中,以后每次用户刷新就可以去session中拿了,这样就不用去数据库中查询了,这是有道理的,但是不能解决上面的问题,因为我们要解决的是多用户去访问同一商品,去点击同一商品,重定向只能保证同一用户去点击或刷新。但是二级缓存可以解决这些问题。

            我们先详细解说一下基于Hibernate4.3的二级缓存技术,然后再针对本项目做一个具体的配置。

    1. Hibernate4.3二级缓存基本配置
            与Hibernate3不同,Hibernate4.3的核心包里没有跟缓存相关的类,我们要用二级缓存的话,需要加上缓存的jar包,从官方下载的hibernate-release-4.3.11.Final中的lib/optional/ehcache中有二级缓存所需要的jar包,先要添加到工程中。如下:

     然后我们在hibernate.cfg.xml中配置二级缓存相关的配置:

     1 <hibernate-configuration>
     2  
     3     <session-factory>
     4         <property name="dialect">
     5             org.hibernate.dialect.MySQLDialect
     6         </property>
     7         
     8         <property name="show_sql">true</property>
     9         
    10         <!-- 配置二级缓存提供商,注意此处并不是缓存的jar包 -->
    11         <property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property>
    12         
    13         <mapping class="cn.it.shop.model.Category" />
    14         <mapping class="cn.it.shop.model.Account" />
    15         <mapping class="cn.it.shop.model.Product" />
    16  
    17         <!-- 配置哪些类支持缓存,这里主要是显示首页的热门商品,所以Product类支持缓存 -->
    18         <class-cache usage="read-only" class="cn.it.shop.model.Product"/>
    19     </session-factory>
    20  
    21 </hibernate-configuration>

    然后我们开启tomcat服务器,然后访问首页,点击热门商品,后台就没有再发送sql语句了,大家可能会纳闷,难道二级缓存就这么简单?配置上面这两个项就搞定了?其实到现在为止,二级缓存已经生效的原因是它有个默认的配置,在上面那个ehcache-core-2.4.3.jar中有个ehcache-failsafe.xml文件,里面已经有了默认配置,我们等会再具体分析。我们先来分析一下Hibernate的查询策略:

    2. Hibernate4.3的查询策略
            Hibernate支持两种查询方式:session查询和hql查询。
            session中有session.save()  update() delete() get() load()等方法,此方式仅仅操作一条记录,默认不用任何配置就支持二级缓存。因此:read-only配置对session是生效的。在session中如果二级缓存中配置了read-only,则session.update()和delete()操作都会失败,如果想要成功,则需要配置成read-write。但是save()和get() load()是成功的。
            hql:此方式默认是用来操作多条记录,比如list()和executeUpdate() 方法。此方式默认二级缓存的配置包括read-only是无效的。hql的list()查询的是多条记录,直接查询数据库,并将查询的结果交给二级缓存,便于get()和load()的调用。executeUpdate也是不支持二级缓存的,也是直接到数据库更新,Hibernate会保证数据库与缓存同步。注意:hql是没有save()方法的,如果需要插入数据只能调用session.save()方法。
           【注】:Hibernate中的一级缓存(默认存在)也称为session级别缓存,不是用来提升性能,而是用来处理事务的;二级缓存为sessionFactory缓存,对所有session都有效,生命周期与sessionFactory相同(sessionFactory是单例,而且项目启动时候就会创建)。

            具体的查询策略,我们看下面的这张图:

    【注】:图片文字如果太小,可以把图片拖到新的窗口看~

            以上就是Hibernate的查询的策略,下面我们来继续看二级缓存的配置。

    3. Hibernate4.3二级缓存高级配置
            上面提到了,我们之所以在hibernate.cfg.xml中配置了两项就可以使用二级缓存,是因为有个默认的配置,下面我们先来看一下这个默认配置:

     1 <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
     2     
     3     <!-- 如果缓存内存溢出,则存储到硬盘空间 -->
     4     <diskStore path="java.io.tmpdir"/>
     5  
     6     <defaultCache
     7         maxElementsInMemory="10000" : <!-- 内存支持的最大对象的数量 -->
     8         eternal="false"     :<!-- 对象是否永久生效,建议为false,这样下面的两个参数才会有效 -->
     9         timeToIdleSeconds="60" :<!-- 对象的间隔周期,默认单位为秒。即60秒后如果还没人用这个对象,会提前销毁 -->
    10         timeToLiveSeconds="120" :<!-- 对象的生命周期,默认单位为秒 -->
    11         overflowToDisk="true"    :<!-- 是否支持溢出到硬盘,建议为true -->
    12          maxElementsOnDisk="10000000" :<!-- 硬盘上支持的最大对象的数量 -->
    13         memoryStoreEvictionPolicy="LRU" :<!-- 对象的替换策略 -->
    14        />     
    15 </ehcache>

     关于默认配置的相关解释已经在上面的注释中了,我们现在知道了,正因为这个默认的配置,才使得Hibernate4.3的二级缓存得以正确执行。现在如果我们要自己进行缓存的配置,就需要自己在src目录下新建一个ehcache.xml文件,然后在里面对上面这些配置项重新配置即可。我们接下来要测试一下各个配置,在测试之前,我先把首页显示的情况贴出来,并编个号,等会测试的时候好说明:

    以上是首页显示的部分内容,Hibernate已经从数据库中帮我们查出了显示信息,并且已经显示好了。我们将它们编个号,等会我们测试缓存的时候就方便分析了。下面我们开始测试一下上面的缓存配置项:

            测试一:测试内存中的对象数量。将配置改成下面情况:

    1 <defaultCache
    2          maxElementsInMemory="6" <!-- 设置只支持缓存6个 -->
    3          eternal="true"
    4          overflowToDisk="false"
    5          memoryStoreEvictionPolicy="FIFO" :<!-- 先进先出 -->
    6          />

    配置好后,我们重启一下服务器,打开首页,由于配置的是6个,所以缓存中只存了最后查出来的6条记录,也就是编号3-8,我们点击3-8中的任何一个商品进入商品详细页面,注意看后台的控制台没有输出任何查询信息,说明并没有发sql语句,但是当我们点击编号2的商品时,后台发了一条sql语句,即查询了数据库,我们后退再次点击2商品,就没有再发sql语句了,说明已经放到缓存里了,但是缓存只支持6条数据,因为配置的对象替换策略是先进先出,所以刚刚缓存中的编号3被移除,我们点击一下3试试,发了一条sql语句,于是测试完毕,二级缓存执行正常。

            测试二:测试对象的生命周期。将配置改成下面的情况:

    1 <defaultCache
    2      maxElementsInMemory="100"
    3      eternal="false" <!-- 配成false才能设置下面的生命周期 -->
    4      timeToIdleSeconds="20" 
    5      timeToLiveSeconds="40"
    6      overflowToDisk="false"
    7      memoryStoreEvictionPolicy="FIFO"
    8      />

    上面配置了缓存的时间为40秒,如果20秒没有操作就移除。由于我们配了100条记录,所以上面编号1-8都在缓存里,我们开启服务器后,随便点击一个,比如点击编号8,没有发出sql语句,正常,20秒后,再点击编号8,发了一条sql语句,说明我们配置的生命周期生效了。这里要注意一下,不能配置太短,比如配置10秒,因为tomcat启动也要好几秒,如果配置少了,还没测试可能时间已经到了……那就不行了。

            测试三: 测试二级缓存是否支持硬盘存储。

    1 <defaultCache
    2      maxElementsInMemory="4"
    3      eternal="false" <!-- 配成false才能设置下面的生命周期 -->
    4      timeToIdleSeconds="100" 
    5      timeToLiveSeconds="200"
    6      overflowToDisk="true"  <!-- 配置成true才支持硬盘存储 -->
    7      memoryStoreEvictionPolicy="FIFO"
    8      />

    我们将支持硬盘存储设置成了true,并将二级缓存最大存储量配置成了4。重启服务器,因为二级缓存最多存4条记录,所以肯定是编号5-8,点击5-8肯定不会发sql语句,但是当我们点击1-4时,也不会发sql语句,因为我们设置了支持硬盘存储,Hibernate将查询结果存在硬盘上了,所以我们也可以直接拿到数据,不需要发sql语句。

            测试四: 测试二级缓存的替换策略

     1 <defaultCache
     2      <!-- 
     3       FIFO已经淘汰了,不会再用了…… 
     4       LRU:最近最少被访问算法(时间策略),会忽略访问频率,离现在最远时间访问的会被替换掉
     5       LFU:最近最未使用算法(频率测量),会忽略访问的先后时间,访问频率最少的会被替换掉
     6      -->
     7      maxElementsInMemory="3"
     8      eternal="false" <!-- 配成false才能设置下面的生命周期 -->
     9      timeToIdleSeconds="100" 
    10      timeToLiveSeconds="200"
    11      overflowToDisk="false"  <!-- 配置成true才支持硬盘存储 -->
    12      memoryStoreEvictionPolicy="LFU"
    13      />

    顾名思义,LRU和LFU分别是关注最后访问时间和访问频率的,我们拿LFU来举例子,现在我们设置了最大存储为3条记录,也就是编号6-8,现在我们依次访问编号6三次,编号7两次,编号8一次,都不会发sql语句,我们再访问编号7,发了sql语句,现在编号7存在了缓存里,编号8已经被移除了,因为它访问的次数最少,我们可以再次点击编号8测试一下,发出了sql语句,测试成功。如果是LRU,则刚刚移除的是编号6,因为编号6最早访问的。

            到这里,相信大家对二级缓存的使用已经掌握了,二级缓存的测试就到这里。下面针对我们这个网上商城的项目做一下配置。

    4. 网上商城项目的实际配置
            我们配置二级缓存的最大记录数为1000,设置生命周期为120秒,间隔周期为60秒,支持硬盘存储,并且使用频率优先(LFU)的替换策略,因为用户点击率高的,肯定要放在二级缓存里。

     1 <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
     2     
     3     <!-- 如果缓存内存溢出,则存储到硬盘空间 -->
     4     <diskStore path="java.io.tmpdir"/>
     5  
     6     <defaultCache
     7             maxElementsInMemory="1000"
     8             eternal="false"
     9             timeToIdleSeconds="60"
    10             timeToLiveSeconds="120"
    11             overflowToDisk="true"
    12             memoryStoreEvictionPolicy="LFU"
    13             />     
    14 </ehcache>

            好了,结合网上商城这个项目,Hibernate4.3的二级缓存配置及使用就介绍完了。

  • 相关阅读:
    EntityFramework 启用迁移 EnableMigrations 报异常 "No context type was found in the assembly"
    JAVA 访问FTP服务器示例(2)
    NuGet Package Manager 更新错误解决办法
    JAVA 访问FTP服务器示例(1)
    RemoteAttribute 的使用问题
    诡异的 javascript 变量
    javascript apply用法
    Babun 中文乱码
    GSM呼叫过程
    转站博客园
  • 原文地址:https://www.cnblogs.com/sharpest/p/9877955.html
Copyright © 2020-2023  润新知