mybatis03 一级缓存 二级缓存

8 篇文章 0 订阅

目录

  1. mybatis的一级缓存
  2. mybatis的二级缓存
  3. 和缓存框架的整合
  4. 二级缓存的问题
  • 一级缓存

        mybatis的一级缓存,指的是在一个SqlSession域内,session没有关闭的时候,执行缓存就会根据sql为key 进行缓存,如果缓存的那个数据进行了数据库操作,比如修改,删除等,mybatis的做法是将它从缓存中清掉,再查询的时候再往缓存里放,能保存缓存的准确性

        mybatis默认支持一级缓存


				public static void main(String[] args) throws IOException {
						SqlSession session=MybatisUtil.oppenSession();
						UserMapper userMapper=session.getMapper(UserMapper.class); 
				
						UserInfo user1=userMapper.getUserById(2);  //进行查询,放缓存
						UserInfo user2=userMapper.getUserById(2);  //命中缓存
						UserInfo user3=userMapper.getUserById(2);  //命中缓存
						UserInfo user6=userMapper.getUserById(3);  //进行查询,放缓存
						UserInfo user7=userMapper.getUserById(2); //命中缓存
						UserInfo user8=userMapper.getUserById(2); //命中缓存
						UserInfo user10=userMapper.getUserById(3); //命中缓存
						UserInfo user11=userMapper.getUserById(3); //命中缓存
				
						session.close();
					}

从日志中可以看到,只输出2条查询语句
                
 一级缓存,离不开 session 域,它的价值

  • 二级缓存
  1. 二级缓存和一级缓存的机制是相同的
  2.  二级缓存与一级缓存机制相同,默认也是用 PerpetualCache (mybatis中关于缓存定义了          一个接口叫Cache,PerpetualCache就是Cache的一个实现类),HashMap存储
  3.  二级缓存和一级缓存的不同在于 作存储用域为 Mapper(Namespace),就是一个namespace下,共享同一份缓存
  4.  可以自定义存储源,比如 Ehcache 

     
     缓存的更新机制 :当某一个作用域(一级缓存的作用域是SqlSesiion,二级缓存的作用域是Namespace),进行了C/U/D (增删改)操作后,
     默认该作用域下,所有的select中的缓存将被 clear ,这一点,一级缓存也是相同的

  • 开启二级缓存  

                 <cache />  //只要这一句就行

  • 关于二级缓存的补充说明

        -- 映射文件中,所有的select语句将会被缓存 
        -- 映射文件中的 所有的 insert ,update,delete 语句都会刷新缓存
        -- 缓存使用 Least Recently Used (最近最少使用的) 的算法进行回收
        -- 缓存会根据指定的时间间隔来刷新
        -- 缓存默认会存储 1024个对象 

  • <cache>这个标签的常用属性

         <cache 
             eviction="FIFO"  //回收策略为先进先出
             flushInterval ="60000" //自动刷新的时间间隔 60s
             size="512" //最多缓存 512个对象 
             readOnly ="true" //只读
             type="org.mybatis.caches.ehcache.LoggingEhcach"  //指定缓存的提供者
           />

  • mybatis 中有 flushCache, useCache两个配置属性,分下面两种情况 

        (1) 当 为select语句的时候, 
            flushCache 默认为false ,表示任何时候这个select语句执行,都不用清空缓存
            userCache 默认为true , 表示对本条语句的执行结果进行缓存,并且使用缓存中的结果

        (2) 当 为 upate,insert,delete 时 
           flushCache 默认为true ,表求执行这条语句,将会清空缓存
           useCache 在该情况下没有,因为一个更新的语句怎么可以使用缓存呢
           
           如果有必要,可以进行手功修改
           
           <select id="save_user" parameterType="xxxxx", flushCache="true" ,useCache="false" >
              ...sql
           </select>

  •  mybatis 和 缓存框架的整合
  1.   EhCache 是一个纯Java的进程内缓存框架,具有快速、精干等特点,是 Hibernate 中默认    CacheProvider。
  2.   Ehcache是一种广泛使用的开源Java分布式缓存。主要面向通用缓存,Java EE和轻量级容       器,它具有内存和磁盘存储,缓存加载器,缓存扩展,缓存异常处理程序,一个gzip缓存              servlet  过滤器,支持REST和SOAP api等特点。
  3.  Ehcache最初是由Greg Luck于2003年开始开发。2009年,该项目被Terracotta购买。软件仍然是开源,但一些新的主要功能(例如,快速可重启性之间的一致性的)只能在商业产品中使用,例如Enterprise EHCache and BigMemory。
  4.     维基媒体Foundationannounced目前使用的就是Ehcache技术。 

    1) 导入 相关的jar包 
       mybatis-ehcache-1.0.3.jar
       ehcache-core-2.6.8.jar
       slf4j-api-1.6.1.jar
    
   2) 在配置文件中 比如 UserMapper.xml 中 
                  //以下两个标签二选一
           <cache type="org.mybatis.caches.ehcache.LoggingEhcache" />   //这个可以输出日志
           <cache type="org.mybatis.caches.ehcache.EhcacheCache" />  //不能输出日志
             
   3) ehcache 的配置文件 ehcache.xml ,放在 config(类路径下) 即可
              

 <?xml version="1.0" encoding="UTF-8"?>
                    <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                    xsi:noNamespaceSchemaLocation="ehcache.xsd" updateCheck="false">
                      <diskStore path="java.io.tmpdir/mybatis/g" />  //如果往磁盘上放,默认放在哪个目录

                        <!-- DefaultCache setting. -->
                        <defaultCache
                            maxEntriesLocalHeap="10000"
                            eternal="false"
                            timeToIdleSeconds="300"
                            timeToLiveSeconds="600"
                            overflowToDisk="true"
                            maxEntriesLocalDisk="100000"
                            memoryStoreEvictionPolicy="LFU"/>
                        
                        <!-- security entity-->
                        <cache
                            name="entityCache"
                            maxEntriesLocalHeap="10000"
                            eternal="true"
                            overflowToDisk="true"
                            maxEntriesLocalDisk="1000000" />
                        </ehcache>
  • 二级缓存的问题

Cache使用时的注意事项

  1.  只能在【只有单表操作】的表上使用缓存
  2. 不只是要保证这个表在整个系统中只有单表操作,而且和该表有关的全部操作必须全部在一个namespace下。        
  3.  在可以保证查询远远大于insert,update,delete操作的情况下使用缓存
  4.  这一点不需要多说,所有人都应该清楚。记住,这一点需要保证在1的前提下才可以!

    附: 关于mybatis中的二级缓存
    可能会有很多人不理解这里,二级缓存带来的好处远远比不上他所隐藏的危害。

  1.     mybatis中 缓存是以namespace为单位的,不同namespace下的操作互不影响。
  2.     insert,update,delete操作会清空所在namespace下的全部缓存。
  3.     通常使用 MyBatis Generator 生成的代码中,都是各个表独立的,每个表都有自己的 namespace。

    

  • 为什么避免使用二级缓存 ?
  1. 在符合【Cache使用时的注意事项】的要求时,并没有什么危害。
  2.  其他情况就会有很多危害了。
  •   针对一个表的某些操作不在他独立的namespace下进行的原因             
  1. 例如在UserMapper.xml中有大多数针对user表的操作。但是在一个XXXMapper.xml中,还有针对user单表的操作。
  2. 这会导致user在两个命名空间下的数据不一致。如果在UserMapper.xml中做了刷新缓存的操作,
  3. 在XXXMapper.xml中缓存仍然有效,如果有针对user的单表查询,使用缓存的结果可能会不正确。
  4. 更危险的情况是在XXXMapper.xml做了insert,update,delete操作时,会导致UserMapper.xml中的各种操作充满未知和风险。

有关这样单表的操作可能不常见。但是你也许想到了一种常见的情况。

  • 多表操作一定不能使用缓存 为什么不能?

            首先不管多表操作写到那个namespace下,都会存在某个表不在这个namespace下的情况。

            例如两个表:role和user_role,如果我想查询出某个用户的全部角色role,就一定会涉及到多表的操作。

                <select id="selectUserRoles" resultType="UserRoleVO">
                    select * from user_role a,role b where a.roleid = b.roleid and a.userid = #{userid}
                </select>

  •  像上面这个查询,你会写到那个xml中呢??
  1. 不管是写到RoleMapper.xml还是UserRoleMapper.xml,或者是一个独立的XxxMapper.xml中。如果使用了二级缓存,都会导致上面这个查询结果可能不正确。
  2. 如果你正好修改了这个用户的角色,上面这个查询使用缓存的时候结果就是错的, 这点应该很容易理解。             
  3. 在我看来,就以MyBatis目前的缓存方式来看是无解的。多表操作根本不能缓存。   
  4. 如果你让他们都使用同一个namespace(通过<cache-ref>)来避免脏数据,那就失去了缓存的意义。 

    看到这里,实际上就是说,二级缓存不能用。再说多了也就没啥用
                

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值