缓存机制
提高运行速度,提高查询效率
MyBatis包含--个非常强大的查询缓存特性它可以非常方便地配置和定制。缓存可以极大的提升查询效率。
mybatis中默认一级缓存
假如有一条数据的查询量非常大,且内容基本不变,那么反复查询就会让数据库压力变大,这时我们就可以将数据存在内存缓存中,这样就大大提高的了查询效率,同时缓解了数据库压力。
一级缓存(本地)和二级缓存(全局)
1、默认情况下,只有一级缓存( SqlSession级别的缓存也称为本地缓存)开启。
2、二级缓存需要手动开启和配置,他是基于namespace级别的缓存。
3、为了提高扩展性。MyBatis定义了缓存接口Cache。我们可以通过实现Cache接口来自定义二级缓存
开始测试
1、一级缓存
(没有用到一级缓存的时候就,效果就是向数据库再次查询一次)
一定要开启log4j,不然看不到效果
引入log4j.jar包
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
把配置文件放在resource下
一定要log4j.properties命名,建议直接复制
# Set root category priority to INFO and its only appender to CONSOLE.
#log4j.rootCategory=INFO, CONSOLE debug info warn error fatal
log4j.rootCategory=debug, CONSOLE, LOGFILE
# Set the enterprise logger category to FATAL and its only appender to CONSOLE.
log4j.logger.org.apache.axis.enterprise=FATAL, CONSOLE
# CONSOLE is set to be a ConsoleAppender using a PatternLayout.
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n
# LOGFILE is set to be a File appender using a PatternLayout.
log4j.appender.LOGFILE=org.apache.log4j.FileAppender
log4j.appender.LOGFILE.File=d:/axis.log
log4j.appender.LOGFILE.Append=true
log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout
log4j.appender.LOGFILE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n
在Mybatis中加配置
<setting name="logImpl" value="STDOUT_LOGGING"/>
测试
可以看出数据库只是执行了一次语句,但是同样输出两次结果,说明第二次是从内存之中直接获得的,连对象都是一样的
(1)SQLsession 不同也会再次查询
当SQLsession不一样时,我用新的SQLsession这时就不在缓存之中取结果了
这说明每个SQLsession会有自己对应缓存
(2)SQLsession 相同,但是查询条件不同
说白了就是缓存中还没有这条数据
(3)SQLsession 相同,两次查询间执行了增删改操作
明明是一样的查询却查询了两次
(4)SQLsession 相同,但是手动清除了缓存
同样执行了两次
2、二级缓存(全局缓存)
基于namespace级别的缓存:一个namespace对应一个二级缓存;
工作机制
1、一个会话,查询一条数据,这个数据会被放在当前会话的一级缓存中;
2、如果会话关闭:如果会话关闭; 一级缓存中的数据会被保存到二级缓存中;新的会话查询信息,就可以参照二级缓存
3、不同的namespace查出的数据会放在自己对应的缓存map中
效果:数据会从二级缓存中获取查出的数据都会被默认先放在一级缓存中。只有会话提交或者关闭以后,一级缓存中的数据才会转移到二级缓存中
开始测试
1、开启二级缓存
<setting name="cacheEnabled" value="true"/>
eviction :缓存的回收策略:
LRU(默认) -最近最少使用的:移除最长时间不被使用的对象。
FIFO -先进先出:按对象进入缓存的顺序来移除它们。
SOFT -软引用:移除基于垃圾回收器状态和软引用规则的对象。
WEAK 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。
flushInterval:缓存刷新间隔缓存多长时间清空一次,默认不清空,设置一个毫秒值
readOnly :是否只读:
true:只读; mybatis认为所有从缓存中获取数据的操作都是只读操作,不会修改数据。mybatis为了加快获取速度,直接就会将数据在缓存中的引用交给用户。不安全,速度快
false非只读: mybati s觉得获取的数据可能会被修改。mybatis会利用序列化&反序列的技术克隆一份新的数据给你。非常安全,但是速度慢
size存放多少元素
type:指定自定义缓存的全类名(默认即可)
2、去mapper.xml中配置
<cache eviction="FIFO" flushInterval="6000" readOnly="false" size="50" >
</cache>
3、对应的实体类要实现序列化接口
测试
注意必须关闭会话,查询的内容才会放到二级缓存中,因为没有关闭的时候查询结果是存在一级缓存中的
将只读开启后结果相等 。
相关的设置
和缓存有关的设置/属性:
1)、cacheEnabled=true:false:关闭缓存(二级缓存关闭)(一级缓存一直可用的)
2)、每个select标签都有useCache="true": false:不使用缓存(一级缓存依然使用,二级缓存不使用)
3)、【每个增删改标签的:flushCache="true":(一级二级都会清除)】增删改执行完成后就会清楚缓存;
测试:flushCache="true":一级缓存就清空了;二级也会被清除; 查询标签:flushCache="false":如果flushCache=true;每次查询之后都会清空缓存;缓存是没有被使用的;
4)、sqlSession.clearCache();只是清楚当前session的一级缓存;
5)、localCacheScope:本地缓存作用域:(一级缓存SESSION);当前会话的所有数据保存在会话缓存中; STATEMENT:可以禁用一级缓存;
缓存原理图