mybatis二级缓存的作用范围_java缓存机制

mybatis二级缓存的作用范围_java缓存机制应用场景:      对于访问多的查询请求且用户对查询结果实时性要求不高,此时可采用mybatis二级缓存技术降低数据库访问量,提高访问速度,业务场景比如:耗时较高的统计分析sql、电话账单查询sql等。      实现方法如下:通过设置刷新间隔时间,由mybatis每隔一段时间自动清空缓存,根据数据变化频率设置缓存刷新间隔flushInterval,比如设置为30分钟、6…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

应用场景:
           对于访问多的查询请求且用户对查询结果实时性要求不高,此时可采用mybatis二级缓存技术降低数据库访问量,提高访问速度,业务场景比如:耗时较高的统计分析sql、电话账单查询sql等。
           实现方法如下:通过设置刷新间隔时间,由mybatis每隔一段时间自动清空缓存,根据数据变化频率设置缓存刷新间隔flushInterval,比如设置为30分钟、60分钟、24小时等,根据需求而定。

局限性:
           mybatis二级缓存对细粒度的数据级别的缓存实现不好,比如如下需求:对商品信息进行缓存,由于商品信息查询访问量大,但是要求用户每次都能查询最新的商品信息,
           此时如果使用mybatis的二级缓存就无法实现当一个商品变化时只刷新该商品的缓存信息而不刷新其它商品的信息,因为mybaits的二级缓存区域以mapper为单位划分,
           当一个商品信息变化会将所有商品信息的缓存数据全部清空。解决此类问题需要在业务层根据需求对数据有针对性缓存。
      缓存都是实现了Cache这个接口…..

如何开启 二级缓存,步骤如下:
        1.导入ehcache相关jar包  (ehcache: 缓存插件,插件:就是对现有应用软件功能的一个扩展)        

      ehcache-core-2.6.5.jar
        mybatis-ehcache-1.1.0.jar

      <dependency>
          <groupId>net.sf.ehcache</groupId>
          <artifactId>ehcache-core</artifactId>
          <version>2.6.6</version>
      </dependency>
      <!-- https://mvnrepository.com/artifact/org.mybatis.caches/mybatis-ehcache -->
      <dependency>
          <groupId>org.mybatis.caches</groupId>
          <artifactId>mybatis-ehcache</artifactId>
          <version>1.1.0</version>
      </dependency>

        2,开启mybatis的二级缓存          

在mybatis核心配置文件mybatis-config.xml中加入

            <settings>
                <!-- 开启二级缓存 -->
                <setting name="cacheEnabled" value="true" />
            </settings>

      3.在classpath下加入ehcache.xml文件
          

<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"
            timeToLiveSeconds="120"
            overflowToDisk="true"
            maxElementsOnDisk="10000000"
            diskPersistent="false"
            diskExpiryThreadIntervalSeconds="120"
            memoryStoreEvictionPolicy="LRU"
            />
			
	<!--
		默认缓存配置,
		以下属性是必须的:
			name :cache的标识符,在一个CacheManager中必须唯一。
			maxElementsInMemory : 在内存中缓存的element的最大数目。
			maxElementsOnDisk : 在磁盘上缓存的element的最大数目。
			eternal : 设定缓存的elements是否有有效期。如果为true,timeouts属性被忽略。
			overflowToDisk : 设定当内存缓存溢出的时候是否将过期的element缓存到磁盘上。

		以下属性是可选的:
			 timeToIdleSeconds : 缓存element在过期前的空闲时间。
			 timeToLiveSeconds : 缓存element的有效生命期。
			 diskPersistent : 在VM重启的时候是否持久化磁盘缓存,默认是false。
			 diskExpiryThreadIntervalSeconds : 磁盘缓存的清理线程运行间隔,默认是120秒.
			 memoryStoreEvictionPolicy : 当内存缓存达到最大,有新的element加入的时候,
				移除缓存中element的策略。默认是LRU,可选的有LFU和FIFO
	-->
</ehcache>

        属性说明:
         diskStore:指定数据在磁盘中的存储位置。
         defaultCache:当借助CacheManager.add(“demoCache”)创建Cache时,EhCache便会采用<defalutCache/>指定的的管理策略
        以下属性是必须的:
         maxElementsInMemory – 在内存中缓存的element的最大数目 
         maxElementsOnDisk – 在磁盘上缓存的element的最大数目,若是0表示无穷大
       eternal – 设定缓存的elements是否永远不过期。如果为true,则缓存的数据始终有效,如果为false那么还要根据timeToIdleSeconds,timeToLiveSeconds判断
         overflowToDisk – 设定当内存缓存溢出的时候是否将过期的element缓存到磁盘上
        以下属性是可选的:
         timeToIdleSeconds – 当缓存在EhCache中的数据前后两次访问的时间超过timeToIdleSeconds的属性取值时,这些数据便会删除,默认值是0,也就是可闲置时间无穷大
         timeToLiveSeconds – 缓存element的有效生命期,默认是0.,也就是element存活时间无穷大
             diskSpoolBufferSizeMB 这个参数设置DiskStore(磁盘缓存)的缓存区大小.默认是30MB.每个Cache都应该有自己的一个缓冲区.
         diskPersistent – 在VM重启的时候是否启用磁盘保存EhCache中的数据,默认是false。
        diskExpiryThreadIntervalSeconds – 磁盘缓存的清理线程运行间隔,默认是120秒。每个120s,相应的线程会进行一次EhCache中数据的清理工作
        memoryStoreEvictionPolicy – 当内存缓存达到最大,有新的element加入的时候, 移除缓存中element的策略。默认是LRU(最近最少使用),可选的有LFU(最不常使用)和FIFO(先进先出)        

4.在UserMapper.xml中开启二缓存,UserMapper.xml下的sql执行完成会存储到它的缓存区域(HashMap)

    <cache type="org.mybatis.caches.ehcache.EhcacheCache">
                <!-- timeToLiveSeconds 缓存自创建日期起至失效时的间隔时间 -->
                <property name="timeToIdleSeconds" value="3600" />

                <!-- timeToIdleSeconds 缓存创建以后,最后一次访问缓存的日期至失效之时的时间间隔 -->
                <property name="timeToLiveSeconds" value="3600" />

                <!-- 同ehcache参数maxElementsInMemory -->
                <property name="maxEntriesLocalHeap" value="1000" />

                <!-- 同ehcache参数maxElementsOnDisk -->
                <property name="maxEntriesLocalDisk" value="10000000" />
                
                <!-- 当内存缓存达到最大,有新的element加入的时候, 移除缓存中element的策略。默认是LRU(最近最少使用),可选的有LFU(最不常使用)和FIFO 
                    (先进先出) -->
                <property name="memoryStoreEvictionPolicy" value="LRU" />
     </cache>


            <!--mybatis ehcache缓存配置 -->
            <!-- 以下两个<cache>标签二选一,第一个可以输出日志,第二个不输出日志 -->
             <cache type="org.mybatis.caches.ehcache.LoggingEhcache" />
           
             <cache type="org.mybatis.caches.ehcache.EhcacheCache"/> 

    测试:需求获取员工表所有记录数(测试二级缓存),
          执行一次查询后,关闭session;然后获得一个全新的Session,再执行查询,若此时控制台未输出sql语句,且磁盘相应缓存目录下有缓存文件产生,证明二级缓存发挥了作用。     
    
sql映射文件中:

<cache type="org.mybatis.caches.ehcache.EhcacheCache">
        <!-- timeToLiveSeconds 缓存自创建日期起至失效时的间隔时间 -->
        <property name="timeToIdleSeconds" value="3600" />

        <!-- timeToIdleSeconds 缓存创建以后,最后一次访问缓存的日期至失效之时的时间间隔 -->
        <property name="timeToLiveSeconds" value="3600" />

        <!-- 同ehcache参数maxElementsInMemory -->
        <property name="maxEntriesLocalHeap" value="1000" />

        <!-- 同ehcache参数maxElementsOnDisk -->
        <property name="maxEntriesLocalDisk" value="10000000" />

        <!-- 当内存缓存达到最大,有新的element加入的时候, 移除缓存中element的策略。默认是LRU(最近最少使用),可选的有LFU(最不常使用)和FIFO
            (先进先出) -->
        <property name="memoryStoreEvictionPolicy" value="LRU" />
    </cache>    

dao实现类中:

 @Override
    public List<Person> selectAll() {
        //步骤:
        //通过工具类获得SqlSession的实例
        SqlSession sqlSession = MyBatisUtil.getSqlSessionInstance();

        List<Person> persons = sqlSession.selectList("com.uplooking.dao.PersonDao.selectAll");
        System.out.println("第一次查询到的员工数是:" + persons);

        //关闭sqlSession(让一级缓存失效)
        MyBatisUtil.releaseResource(sqlSession);

        //执行完下面的代码行,控制台若没有sql语句输出,证明结果来自于二级缓存,而不是重新查询的数据库。
        sqlSession = MyBatisUtil.getSqlSessionInstance();
        persons = sqlSession.selectList("com.uplooking.dao.PersonDao.selectAll");
        System.out.println("第二次查询到的员工数是:" + persons);

        //释放资源
        MyBatisUtil.releaseResource(sqlSession);

        return persons;
    }

建议:放弃二级缓存,在业务层使用可控制的缓存代替更好。
<select id=”selectUserRoles” resultType=”UserRoleVO”>
    select * from user_role a,role b where a.roleid = b.roleid and a.userid = #{userid}
</select>
像上面这个查询,你会写到那个xml中呢??
不管是写到RoleMapper.xml还是UserRoleMapper.xml,或者是一个独立的XxxMapper.xml中。如果使用了二级缓存,都会导致上面这个查询结果可能不正确。
如果你正好修改了这个用户的角色,上面这个查询使用缓存的时候结果就是错的。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/191453.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 【Stream流】Sort排序详解「建议收藏」

    【Stream流】Sort排序详解「建议收藏」很多时候由于需求的复杂性,很多直接从数据库查出的数据并不能直接返回前端,需要进行处理,处理之后又需要排序,这时候一般都会使用Stream流的Sort排序场景一:普通排序正序(升序)list=list.stream().sorted().collect(Collectors.toList());或者list.stream().sorted(Comparator.comparing(Student::getAge))倒序(降序)list.stream().sorted(Comparator.

    2022年8月12日
    7
  • 细说php读书笔记_细说php自测题

    细说php读书笔记_细说php自测题今天我们来读这本书是兄弟连出版社出版的《细说PHP》,买它的原因是,我的PHP是跟着网上视频自学的。后来第一份工作是使用早些年流行的PHPCMS开发。phpcms并不是一款产品,它是一系列产品,当时市场对于cms这个概念其实不是太严谨,因为除了phpcms、dedecms、连discuz、ecshop也都被归类进去了。哦,还有帝国cms,它出品的火车头采集器当时可以说相当好用,后来因为工作需求,就自己写采集器了。正式因为这些cms系统的出现,再加上php语言本身易学易入门的特…

    2022年10月30日
    0
  • Pycharm 最新激活码 2021[免费获取]

    (Pycharm 最新激活码 2021)好多小伙伴总是说激活码老是失效,太麻烦,关注/收藏全栈君太难教程,2021永久激活的方法等着你。IntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,下面是详细链接哦~https://javaforall.net/100143.htmlMLZPB5EL5Q-eyJsaWNlbnNlSWQi…

    2022年3月21日
    51
  • 如何使用cmd进入MySQL

    如何使用cmd进入MySQL同时按下键盘上的win徽标+R,选择cmd,回车键打开cmd,在命令行中输入mysql-uroot-p切记只有这句话“mysql-uroot-p”,p后面没有分号“;”,否则就会报出以下错误,即提醒使用者不要在cmd命令行中输入密码,这种做法是不安全的。正确示例:C:\Users\hemiao>mysql-uroot-pEnterpassword:******WelcometotheMySQLmonitor.Commandsendwith;or

    2022年6月5日
    67
  • CareerCup它1.8 串移包括问题

    CareerCup它1.8 串移包括问题

    2022年1月2日
    41
  • 致 Python 初学者「建议收藏」

    致 Python 初学者「建议收藏」欢迎来到“Python进阶”专栏!来到这里的每一位同学,应该大致上学习了很多Python的基础知识,正在努力成长的过程中。在此期间,一定遇到了很多的困惑,对未来的学习方向感到迷茫。我非常理解你们所面临的处境。我从2007年开始接触python这门编程语言,从2009年开始单一使用python应对所有的开发工作,直至今天。回顾自己的学习过程,也曾经遇到过无数的困难,也曾经迷茫过、困惑过。开办这个专栏,正是为了帮助像我当年一样困惑的Python初学者走出困境、快速成长。希望我的经验能真正帮到你

    2022年4月27日
    36

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号