发表于: 2018-03-12 23:35:10

1 484


今天完成的事情:

1. mybatis 的缓存

明天计划的事情

1. 学习hibernate的缓存机制

2. 再投校招


遇到的问题:


收获:

1. mybatis 的一级缓存

一级缓存默认情况下是开启的,存储结构是HashMap, 作用域是每一个sqlSession( 两个之间的内容不共享 ),生命和sqlSession一致。

每一次开启一个和数据库的会话,就创建出一个sqlSession ,在这个对话里进行的查询会被缓存下来




一级缓存的实现:

SqlSession: 对外提供了用户和数据库之间交互需要的所有方法,隐藏了底层的细节。它的一个默认实现类是DefaultSqlSession。

Executor: SqlSession向用户提供操作数据库的方法,但和数据库操作有关的职责都会委托给Executor。

BaseExecutor: BaseExecutor是一个实现了Executor接口的抽象类,定义若干抽象方法,在执行的时候,把具体的操作委托给子类进行执行。

Cache: Mybatis中的Cache接口,提供了和缓存相关的最基本的操作,有若干个实现类,使用装饰器模式互相组装,提供丰富的操控缓存的能力。


由sqlSession 创建一个Executor 执行器,

Executor接口的实现类BaseExecutor中拥有一个Cache接口的成员变量之一的PerpetualCache,就是对Cache接口最基本的实现,其实现非常的简内部持有了hashmap,对一级缓存的操作其实就是对这个hashmap的操作。


基于以上:当有两个SqlSession的时候,当两个同时对一条数据查询后,其中一个执行了更新/删除/添加的操作的时候,该SQlSession的相应的缓存清除


另一个SQLSession查询出来的数据是从该sqlSession创建的缓存里取数据,所以数据不变,为脏数据。


主要步骤如下:

  1. 对于某个Select Statement,根据该Statement生成key。
  2. 判断在Local Cache中,该key是否用对应的数据存在。
  3. 如果命中,则跳过查询数据库,继续往下走。
  4. 如果没命中:
    1  去数据库中查询数据,得到查询结果;
    2  将key和查询到的结果作为key和value,放入Local Cache中。
    3. 将查询结果返回;
  5. 判断缓存级别是否为STATEMENT级别,如果是的话,清空本地缓存。


建议是把一级缓存的默认级别设定为Statement,即不使用一级缓存。

因为当有多个SQLSession 的时候会脏读。


得知缓存实际上为一个HashMap,那么KEY是什么?

它将MappedStatement的Id、sql的offset、Sql的limit、Sql本身以及Sql中的参数传入了CacheKey这个类,最终生成了CacheKey

而且缓存没有有效时间和  做容量限定,为什么?

1.  一般而言SqlSession的生存时间很短。一般情况下使用一个SqlSession对象执行的操作不会太多,执行完就会消亡;
2.  对于某一个SqlSession对象而言,只要执行update、insert、delete ,都会将这个SqlSession对象中对应的一级缓存在执行前清空掉,所以一般情况下不会出现缓存过大,影响JVM内存空间的问题;
3. 可以手动地释放掉SqlSession对象中的缓存。



2. mybatis 的二级缓存(存储结构和一级一样)



二级缓存是基于每一个mapper.xml里的nameSpace(nameSpace是把xml对应到具体的model

在一个nameSpace的下面,所有的SQL语句都是在同一个cache下。也就是说在同一个nameSpace的不同SqlSession是共享缓存。

Mybatis的映射XML中配置cache或者 cache-ref 。

每一个Cache对象,都会有一个自己所属的namespace命名空间,并且会将Mapper的 namespace作为它们的ID。

所以如果想要进行连表的操作,却又不会造成脏读(原理同一级缓存)

如果你想让多个Mapper公用一个Cache的话,你可以使用<cache-ref namespace="">节点,来指定你的这个Mapper使用到了哪一个Mapper的Cache缓存。




开启二级缓存配置:

1 在Mybatis的配置文件中开启二级缓存。

2. 在Mybatis的映射XML中

 <cache eviction="FIFO" flushInterval="60000" readOnly="false" size="1024"></cache>

除此之外,还要再xml文件下的sql语句的标签下配置useCache="true",Mapper才会对此Select的查询支持缓存特性,否则,不会对此select查询,不会经过Cache缓存。而却xml对应的model必须实现序列化接口。


1、eviction=“FIFO”:缓存回收策略:• 默认的是 LRU。

  • LRU – 最近最少使用的:移除最长时间不被使用的对象。
  • FIFO – 先进先出:按对象进入缓存的顺序来移除它们。
  • SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。
  • WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。

2、flushInterval:刷新间隔,单位毫秒

  • 默认情况是不设置,也就是没有刷新间隔,缓存仅仅调用语句时刷新

3、size:引用数目,正整数

  • 代表缓存最多可以存储多少个对象,太大容易导致内存溢出

4、readOnly:只读,true/false

  • true:只读缓存;会给所有调用者返回缓存对象的相同实例。因此这些对象不能被修改。这提供了很重要的性能优势。
  • false:读写缓存;会返回缓存对象的拷贝(通过序列化)。这会慢一些,但是安全,因此默认是 false。


如果想要自定义缓存

<cache type="org.mybatis.caches.ehcache.EhcacheCache"></cache>


3。 一个mybatis可以很好结合的第三方缓存框架EhCache 






返回列表 返回列表
评论

    分享到