Mybatis学习--17.Mybatis的缓存
Mybatis的缓存
- 在mybatis中提供了一种缓存机制,内存中有一块区域用来存放从数据库中查询的结果。当下次再执行相同的查询语句时,就不需要通过IO的方式从数据库中取数据(数据库中的数据实际上是存放在硬盘文件中),而是直接从缓存中取数据。一方面减少了IO操作次数,另一方面不再执行繁琐的查询算法,提高了查询效率。
- 缓存机制是计算机中优化性能的一种重要手段。比如计算机系统中cache,java中的字符串常量池,整数常量池(-127-128),线程池、连接池等。都是缓存机制的应用
- mybatis缓存包括:一级缓存(将查询的结果存储到SqlSession中)、二级缓存(将查询的结果存储到SqlSessionFactory中)或者集成第三方的缓存
- mybatis的缓存机制只针对DQL语句(select),目的是提高查询效率
一级缓存
一级缓存是默认开启的,不需要配置
如果在同一个SqlSession对象执行相同的select语句,就会使用缓存机制,只在第一次执行select语句,其余语句不会执行,而是直接从缓存中取出结果返回。
当SqlSession对象不同或者查询条件不同时,不会使用缓存机制
一级缓存失效的条件
- 调用SqlSession的clearCache方法,进行手动清空缓存
- 只要执行insert、delete或update语句都会使一级缓存清空,即使这些语句是对另一张表的操作
@Test public void testSelectById(){ SqlSession sqlSession = SqlSessionUtil.getSqlSession(); CarMapper mapper = sqlSession.getMapper(CarMapper.class); Car car1 = mapper.selectById(12L); System.out.println(car1); //sqlSession.clearCache(); Car car2 = mapper.selectById(12L); System.out.println(car2); sqlSession.close(); }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
* Preparing: select * from t_car where id = ?
##### 二级缓存
* 二级缓存的作用范围为整个SqlSessionFactory(一个SqlSessionFactory对应一个数据库)
* 如何使用二级缓存
1. 在mybatis核心配置文件的settings标签中开启二级缓存机制,不过由于mybatis中默认开启二级缓存,所以不需要配置
2. 在需要使用二级缓存的SqlMapper.xml文件中添加<cache/>标签
3. 使用二级缓存的实体类必须可序列化,即实现java.io.Serializable接口
4. 只有当SqlSession对象关闭或提交后,一级缓存中的数据才会写入二级缓存中,二级缓存才会生效
* 一级缓存的优先级高于二级缓存
* 二级缓存失效的条件
* 只要执行insert、delete或update语句都会使一级缓存清空,即使这些语句是对另一张表的操作
* 二级缓存的相关配置
* 在cache标签中有很多属性
* eviction:指定从缓存中移除某个对象的淘汰算法,默认使用LRU策略
* LRU:least recently used,最近使用次数少的对象,优先淘汰在间隔时间内使用频率最低的对象
* FIFO:first in first out,先进入缓存中的对象先被淘汰
* SOFT:优先淘汰软引用指向的对象,与JVM的垃圾回收算法相关
* WEAK:优先淘汰弱引用指向的对象,与JVM的垃圾回收算法相关
* flushinterval:设置二级缓存的刷新间隔。默认不刷新
* readonly:
a. 值为true时,多条相同sql语句返回的对象是同一个,性能好,但有线程安全问题
b. 值为false时,多条相同sql语句返回的对象是副本对象,调用了clone方法,线程安全但性能一般
* size:设置缓存中可以存放对象的最大数量,默认值为1024
* ```java
public void testSelectByIdWithDifSqlS() throws Exception{
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));
SqlSession sqlSession1 = sqlSessionFactory.openSession();
SqlSession sqlSession2 = sqlSessionFactory.openSession();
CarMapper mapper1 = sqlSession1.getMapper(CarMapper.class);
CarMapper mapper2 = sqlSession2.getMapper(CarMapper.class);
Car car1 = mapper1.selectById(12L);
System.out.println(car1);
sqlSession1.close();
Car car2 = mapper2.selectById(12L);
System.out.println(car2);
}Preparing: select * from t_car where id = ?
集成第三方的缓存
以Ehcache三方缓存器为例
这种第三方的缓存器可以替代mybatis中的二级缓存,无法替代一级缓存
使用步骤
引入Ehcache依赖
<dependency> <groupId>org.mybatis.caches</groupId> <artifactId>mybatis-ehcache</artifactId> <version>1.2.3</version> </dependency>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
2. 在mybatis的根路径下新建ehcache.xml文件,并配置以下信息
* ```xml
<?xml version="1.0" encoding="UTF-8" ?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"
updateCheck="false">
<defaultCache
eternal="false"
maxElementsInMemory="10000"
overflowToDisk="false"
diskPersistent="false"
timeToLiveSeconds="3600"
timeToIdleSeconds="0"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU"/>
<cache
name="user"
eternal="false"
maxElementsInMemory="10000"
overflowToDisk="false"
diskPersistent="false"
timeToLiveSeconds="3600"
timeToIdleSeconds="0"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU"/>
<!-- 存储到磁盘时的路径-->
<diskStore path="/Users/wuhanxue/Downloads/ehcache" />
</ehcache>
修改cache标签,添加type属性
<cache type="org.mybatis.caches.ehcache.EhcacheCache"></cache>
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 dch'blog!