发表于: 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创建的缓存里取数据,所以数据不变,为脏数据。
主要步骤如下:
- 对于某个Select Statement,根据该Statement生成key。
- 判断在Local Cache中,该key是否用对应的数据存在。
- 如果命中,则跳过查询数据库,继续往下走。
- 如果没命中:
1 去数据库中查询数据,得到查询结果;
2 将key和查询到的结果作为key和value,放入Local Cache中。
3. 将查询结果返回; - 判断缓存级别是否为STATEMENT级别,如果是的话,清空本地缓存。
建议是把一级缓存的默认级别设定为Statement,即不使用一级缓存。
因为当有多个SQLSession 的时候会脏读。
得知缓存实际上为一个HashMap,那么KEY是什么?
它将MappedStatement的Id、sql的offset、Sql的limit、Sql本身以及Sql中的参数传入了CacheKey这个类,最终生成了CacheKey
而且缓存没有有效时间和 做容量限定,为什么?
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
评论