010,Mybatis缓存

Mybatis缓存


V哥官网:http://www.vgxit.com

本文对应视频教程:http://www.vgxit.com/course/22


1,概述:

我们使用的数据库是把数据存储在磁盘上的,每次读取数据需要数据库从磁盘上把数据索引出来。从硬件的角度分析,索引磁盘是一个较为缓慢的过程,读取内存或者高速缓存处理器的速度要比读取磁盘速度快很多,有可能达到几十倍或者几百倍。但是内存和高速缓存存储数据空间有限,所以,我们一般只会把命中率高的数据缓存起来。mybatis也支持缓存,Mybatis的缓存分为一级缓存和二级缓存,我们接下来慢慢介绍。


2,一级缓存:

一级缓存是在SqlSession上的缓存。这个的意思就是,对于同一个SqlSession,只要这个SqlSession没有被关闭,那么一级缓存就有效。一级缓存默认情况下就是开启的。

我们来做一个实验:

package com.vgxit.learn.vgmybatis.ktdm.test;

import com.vgxit.learn.vgmybatis.ktdm.mapper.UserMapper;
import com.vgxit.learn.vgmybatis.ktdm.po.User;
import com.vgxit.learn.vgmybatis.ktdm.tool.MybatisTool;
import org.apache.ibatis.session.SqlSession;
import java.io.IOException;

public class Mybatis004Test {
    public static void main(String[] args) throws IOException {
        try (SqlSession sqlSession = MybatisTool.getSqlSession()) {
            UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
            User user = userMapper.getUserById(1);
            System.out.println(user);
            User user1 = userMapper.getUserById(1);
            System.out.println(user);
        }
        try (SqlSession sqlSession = MybatisTool.getSqlSession()) {
            UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
            User user = userMapper.getUserById(1);
            System.out.println(user);
        }
    }
}

从上面我们可以看到如果SqlSession没有被关闭,那么无论你获取多少次数据,只会发送一条sql去数据库查询第二次获取的时候,直接从缓存中获取,不会再次发送sql了。如果SqlSession关闭了,我们重新获取了一个SqlSession,这个时候如果我们再去查询,又会再发一条sql。Mybatis一级缓存的策略是什么?

接下来,我们再定义一个方法获取User数据。而获取的Sql和我们上面的getUserById一模一样。

User loadById(int id);
<select id="loadById" parameterType="int" resultType="com.vgxit.learn.vgmybatis.ktdm.po.User">
        select <include refid="allFields"/> from user where id=#{id}
    </select>

接下来我们直接查询了两次,一次通过getUserById,一次通过loadById

package com.vgxit.learn.vgmybatis.ktdm.test;

import com.vgxit.learn.vgmybatis.ktdm.mapper.UserMapper;
import com.vgxit.learn.vgmybatis.ktdm.po.User;
import com.vgxit.learn.vgmybatis.ktdm.tool.MybatisTool;
import org.apache.ibatis.session.SqlSession;
import java.io.IOException;

public class Mybatis004Test {
    public static void main(String[] args) throws IOException {
        try (SqlSession sqlSession = MybatisTool.getSqlSession()) {
            UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
            User user = userMapper.getUserById(1);
            System.out.println(user);
            User user1 = userMapper.loadById(1);
            System.out.println(user);
        }
    }
}

然后我们发现运行结果打印了两次sql,证明发送了两次sql到数据库查询数据。而这两条sql和对应的参数完全是一样的。这个说明Mybatis判断是不是同一条数据的办法是"方法名+参数",如果方法名和参数都完全匹配的情况下,就直接走一级缓存,否则在查询一次。


3,二级缓存:

二级缓存也叫做SqlSessionFactory级别的缓存,只要SqlSessionFactory不消失缓存都会存在。我们之前也说过,SqlSessionFactory是不是应该存在于整个Mybatis应用运行的阶段。所以说,只要你不关闭应用的进程,那么这个缓存永远都存在。

开启二级缓存的办法:

1,在映射文件上加上<cache/>标签。

2,把对应的PO变成可序列化的:

public class User implements Serializable

3,然后使用如下代码测试:

package com.vgxit.learn.vgmybatis.ktdm.test;

import com.vgxit.learn.vgmybatis.ktdm.mapper.UserMapper;
import com.vgxit.learn.vgmybatis.ktdm.po.User;
import com.vgxit.learn.vgmybatis.ktdm.tool.MybatisTool;
import org.apache.ibatis.session.SqlSession;
import java.io.IOException;

public class Mybatis004Test {
    public static void main(String[] args) throws IOException {
        try (SqlSession sqlSession = MybatisTool.getSqlSession()) {
            UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
            User user = userMapper.getUserById(1);
            System.out.println(user);
        }
        try (SqlSession sqlSession = MybatisTool.getSqlSession()) {
            UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
            User user = userMapper.getUserById(1);
            System.out.println(user);
        }
    }
}

运行结果,我们发现只发了一条sql。这个就是我们的二级缓存,我们关闭了SqlSession之后,只要SqlSessionFacotry还存在,那么就会直接从缓存中获取。

如果我们把第二个获取改成loadById呢?我们可以看到,发送了两条sql去查询。这个就证明二级缓存的缓存策略和一级缓存是一模一样的。

特别说明:我们不推荐使用二级缓存,因为二级缓存的危害是非常大的。因为二级缓存及时namespace的缓存,也就是基于Mapper的。首先如果我们使用了insert,update,delete等等,mybatis会清空当前namespace下面的所有缓存。这个就会造成非常大的性能开销。第二,因为二级缓存是基于namespace的,可能会造成不同namespace下针对同一个数据,他们的查询结果不一样。


4,最佳实践:

这里我们说一下,因为一级缓存mybatis自动就开启了,而二级缓存我们又不推荐使用,而mybatis默认是没有开启的。所以针对Mybatis的缓存策略,我们压根就不要操心,就用默认的就好了。那有的同学可能就说了,老师,既然什么都不管,你给我们花了那么多时间讲这一章的知识是不是白讲了呢?其实,老师觉得还是没有,学习一门东西不但要学习怎么用,还要学习为什么。虽然我们开发的时候不用管,但是Mybatis缓存的原理的掌握,对于我们来说还是很有帮助的。

因为开发的时候,我们不会去使用二级缓存,所以,基于Annotation我们就不去介绍了

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,142评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,298评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,068评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,081评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,099评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,071评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,990评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,832评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,274评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,488评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,649评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,378评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,979评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,625评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,796评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,643评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,545评论 2 352

推荐阅读更多精彩内容