Mybatis一级缓存和二级缓存

Mybatis一级缓存和二级缓存

一级缓存

一级缓存使用的时候,因为缓存不能跨会话共享,不同的会话之间对于相同的数据可能有不一样的缓存。在有多个会话或分布式环境下,会查到过时数据的问题。如果要解决这个问题,就需要用到二级缓存。
一级缓存是基于SqlSession,SqlSession销毁或执行Update、insert、Delete会清除一级缓存。
一级缓存默认SESSION,默认是开启状态;通过localCacheScope设置STATEMENT即可关闭

二级缓存

二级缓存是用来解决一级缓存不能跨会话共享的问题,范围是namespace级别的,可以被多个SqlSession共享(只要是一个接口里面的相同方法,都可以共享),生命周期和应用同步。
二级缓存的总开关默认是开启的。但是每个Mapper的二级缓存开关默认是关闭的。一个Mapper要用到二级缓存,还需要单独打开它自己的开关。

在这里插入图片描述

一级缓存关闭验证

<settings>
	<setting name="localCacheScope" value="STATEMENT"/>
</settings>

测试代码:

	@Test
  	public void select() throws IOException {
        String resource = "mybatis-config.xml";
        InputStream resourceAsStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
        SqlSession sqlSession = sqlSessionFactory.openSession();
        try{
            BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);
            System.out.println("第一次执行:"+mapper.selectBlogById(1));
            System.out.println("第二次执行:"+mapper.selectBlogById(1));
        }finally{
            sqlSession.close();
        }
    }

验证结果:
在这里插入图片描述
一级缓存开启验证

<settings>
	<setting name="localCacheScope" value="SESSION"/>
</settings>

测试代码:不变
测试结果:
在这里插入图片描述
二级缓存开关
1.全局开关

<settings>
	<setting name="cacheEnabled" value="false"/>
</settings>

2.局部开关

<mapper namespace="com.mybatis.cache.mapper.BlogMapper">
	<!-- 声明这个namespace使用二级缓存 -->
	<!-- (1)<cache/> -->
	
	<!-- (2)也可以自定义缓存配置属性,开启二级缓存二选一即可 -->
	<cache type="org.apache.ibatis.cache.impl.PerpetualCache"
               size="1024"
               eviction="LRU"
               flushInterval="120000"
               readOnly="false"/>
</mapper>

cache属性详解

属性含义取值
type缓存实现类需要实现Cache接口,默认是PerpetualCache,可以使用第三方缓存
size最多缓存对象个数默认1024
eviction回收策略(缓存淘汰算法)LUR - 最近最少使用;移除最长时间不被使用的对象(默认)
FIFO - 先进先出;按对象进入缓存的顺序来移除它们.
SOFT - 软引用: 移除基于垃圾回收器状态和软引用规则的对象.
WEAK - 弱引用:更积极的移除基于垃圾收集器状态和弱引用规则的对象
flushInterval定时自动清空缓存间隔自动刷新时间,单位ms,未配置时只有调用时的刷新
readOnly是否只读true: 只读缓存:会给所有调用者返回缓存对象的相同实例。因此这些对象不能被修改。这提供来很重要的性能优势。
false: 读写缓存:会返回缓存对象的拷贝(通过序列化),不会共享。这会慢一些,但是安全,因此默认是false
改为false可读写时,对象必须支持序列化.
blocking启用阻塞缓存通过在get/put方式中加锁,保证只有一个线程操作缓存,基于java重入锁实现

3.局部方法开关

flushCache	将其设置为 true 后,只要语句被调用,都会导致本地缓存和二级缓存被清空,默认值:false。
useCache	将其设置为 true 后,将会导致本条语句的结果被二级缓存缓存起来,默认值:对 select 元素为 true。
<select id="selectList" resultMap="BaseResultMap" useCache="false">
        select * from table
    </select>

代码测试:

@Test
    public void update() throws IOException {
        String resource = "mybatis-config.xml";
        InputStream resourceAsStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
        SqlSession sqlSession1 = sqlSessionFactory.openSession();
        SqlSession sqlSession2 = sqlSessionFactory.openSession();
        try {
            BlogMapper mapper1 = sqlSession1.getMapper(BlogMapper.class);
            BlogMapper mapper2 = sqlSession1.getMapper(BlogMapper.class);

            System.out.println("第一次执行:"+mapper1.selectBlogById(1));
            System.out.println("第二次执行:"+mapper2.selectBlogById(1));
        } finally {
            sqlSession1.close();
            sqlSession2.close();
        }
    }

测试结果:
在这里插入图片描述
二级缓存需要跟事务绑定才能生效
代码测试:

@Test
    public void update() throws IOException {
        String resource = "mybatis-config.xml";
        InputStream resourceAsStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
        SqlSession sqlSession1 = sqlSessionFactory.openSession();
        SqlSession sqlSession2 = sqlSessionFactory.openSession();
        try {
            BlogMapper mapper1 = sqlSession1.getMapper(BlogMapper.class);
            BlogMapper mapper2 = sqlSession2.getMapper(BlogMapper.class);
            Blog blog = mapper1.selectBlogById(1);
            System.out.println("第一次执行:"+blog);
            sqlSession1.commit();

            System.out.println("第二次执行:"+mapper2.selectBlogById(1));
        } finally {
            sqlSession1.close();
            sqlSession2.close();
        }
    }

测试结果:
在这里插入图片描述
测试不同session修改数据库,查询数据是否是二级缓存数据
测试代码:

@Test
    public void update2() throws IOException {
        String resource = "mybatis-config.xml";
        InputStream resourceAsStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
        SqlSession sqlSession1 = sqlSessionFactory.openSession();
        SqlSession sqlSession2 = sqlSessionFactory.openSession();
        SqlSession sqlSession3 = sqlSessionFactory.openSession();
        try {
            BlogMapper mapper1 = sqlSession1.getMapper(BlogMapper.class);
            BlogMapper mapper2 = sqlSession2.getMapper(BlogMapper.class);
            BlogMapper mapper3 = sqlSession3.getMapper(BlogMapper.class);
            Blog blog = mapper1.selectBlogById(1);
            System.out.println("第一次执行:"+blog);
            sqlSession1.commit();//提交事务

            blog.setName("xxxx");
            System.out.println("第二次执行修改:"+mapper2.updateByPrimaryKey(blog));
            sqlSession2.commit();

            System.out.println("第三次执行:"+mapper3.selectBlogById(1));
        } finally {
            sqlSession1.close();
            sqlSession2.close();
            sqlSession3.close();
        }
    }

测试结果:
图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值