码迷,mamicode.com
首页 > 其他好文 > 详细

(十)mybatis之缓存

时间:2017-09-29 11:05:07      阅读:155      评论:0      收藏:0      [点我收藏+]

标签:find   ror   XML   static   一级缓存   size   共享   统一   UI   

一、缓存的意义

  • 将用户经常查询的数据放在缓存(内存)中,用户去查询数据就不用从磁盘上(关系型数据库数据文件)去查询,从缓存中进行查询,从而提高查询效率,解决了高并发系统的性能问题。

 

 

 

 

二、mybatis持久层缓存

技术分享

  • mybatis一级缓存是一个Sqlsession级别,SqlSession只能访问自己的一级缓存数据,二级缓存是跨SqlSession的,是mapper级别的缓存,对于mapper级别的缓存 不同的SqlSession是可以共享的。

 

三、一级缓存

  3.1  原理

技术分享

  • 流程:  第一次发出sql语句查询id为1的用户时,sql查询的结果写入sqlSession一级缓存中,缓存使用的数据结构是一个map<key,value>
key: hashcode+sql+sql输入参数+sql输出参数 (作为SQL的唯一标识)

value: 用户信息。

同一个sqlSession再次发出相同的sql,就从缓存中取数据,不再查询数据库。如果两次中间出现commit操作(修改、添加、删除),此SqlSession中的一级缓存数据全部清空,下次再去缓存中就会查询不到数据再从数据库查询,从数据库查询到后再写入缓存。
每次查询都先从缓存进行查询。
注意:清空时会清空当前sqlsession缓存区域中的全部内容。

 

   3.2  一级缓存配置

  •  mybatis默认支持一级缓存不需要配置
  • 注意:mybatis和Spring整合后进行mapper代理开发,不支持一级缓存,mybatis和Spring整合,Spring按照mapper的模板去生成mapper代理对象,模板中在最后统一关闭sqlsession。

 

 四、二级缓存

  4.1  二级缓存原理

技术分享

 

 

  • 二级缓存的范围是mapper级别(mapper同一个命名空间),mapper以命名空间为单位创建缓存数据结构,结构为map<key,value>
   每次查询先看是否开启二级缓存,如果开启先从二级缓存中数据结构中取缓存数据。
     如果从二级缓存中没有取到,再从一级缓存中进行查找,如果一级缓存也没有,从数据库查询。

 

   4.2  mybatis二级缓存配置

  • mybaits的二级缓存是mapper范围级别,除了在SqlMapConfig.xml设置二级缓存的总开关,即:<setting name="cacheEnabled" value="true"/>

,还要在具体的mapper.xml中开启二级缓存,即:

<mapper namespace="com.shyroke.mapper.OrderMapper">
  <cache />
</mapper>

 

  4.3  注意

  • mybatis二级缓存需要将查询结果映射的pojo实现 java.io.serializable接口,如果不实现则抛出异常:org.apache.ibatis.cache.CacheException: Error serializing object.  Cause: java.io.NotSerializableException
  • 二级缓存可以将内存中的数据写到硬盘,存在对象的序列和反序列化,所以要实现java.io.serializable接口。如果结果映射的pojo中还关联了别的pojo,那么它和它所关联的pojo也都要实现java.io.serializable接口。

技术分享

 

   4.4  二级缓存的禁用

  •  对于变化频率较高的sql,需要禁用二级缓存: 在statement中设置useCache=false可以禁用当前select语句的二级缓存,即每次查询都会发出sql去查询,默认情况是true,即该sql使用二级缓存。
    <select id="findOrderListResultMap" resultMap="ordersUserMap" useCache="false">

 

   4.5  刷新缓存

  • 如果SqlSession操作commit操作,对二级缓存进行刷新(全局清空)
设置与commit相关statement(insert,update,delete等标签)的flushCache属性是否刷新缓存,默认值是true,如果设置了为false,即使后台数据库发生了变化,只要缓存没有过期,也只会读取缓存中数据 就会获取不到最新数据。

 

  4.6 测试

public static void main(String[] args) throws IOException {
        String resource = "resource/mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        SqlSession session = sessionFactory.openSession();
        SqlSession session2 = sessionFactory.openSession();
        
        OrderMapper orderMapper = session.getMapper(OrderMapper.class);
        OrderMapper orderMapper2 = session2.getMapper(OrderMapper.class);
        
        Customer customer=orderMapper.findCustomerById(1);
        System.out.println(customer);
        
        //关闭session,将信息写入二级缓存中
        session.close();
        
        Customer customer2=orderMapper2.findCustomerById(1);
        System.out.println(customer2);
        
    }
  • 注意:只有关闭sqlSession的时候,才会把信息写入二级缓存中。

 

  4.7  mybatis自带的cache参数属性(了解)

mybatis的cache参数只适用于mybatis维护缓存。
  • flushInterval(刷新间隔)可以被设置为任意的正整数,而且它们代表一个合理的毫秒形式的时间段。默认情况是不设置,也就是没有刷新间隔,缓存仅仅调用语句时刷新。 size(引用数目)可以被设置为任意正整数,要记住你缓存的对象数目和你运行环境的可用内存资源数目。默认值是1024。
    readOnly(只读)属性可以被设置为true或false。只读的缓存会给所有调用者返回缓存对象的相同实例。因此这些对象不能被修改。这提供了很重要的性能优势。可读写的缓存会返回缓存对象的拷贝(通过序列化)。这会慢一些,但是安全,因此默认是false。
    如下例子:
    <cache  eviction="FIFO"  flushInterval="60000"  size="512"  readOnly="true"/>
    这个更高级的配置创建了一个 FIFO 缓存,并每隔 60 秒刷新,存数结果对象或列表的 512 个引用,而且返回的对象被认为是只读的,因此在不同线程中的调用者之间修改它们会导致冲突。可用的收回策略有, 默认的是 LRU:
    LRU – 最近最少使用的:移除最长时间不被使用的对象。
    FIFO – 先进先出:按对象进入缓存的顺序来移除它们。
    SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。
    WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。

 

(十)mybatis之缓存

标签:find   ror   XML   static   一级缓存   size   共享   统一   UI   

原文地址:http://www.cnblogs.com/shyroke/p/7609915.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!