您现在的位置是:网站首页> 内容页

MyBatis 一级缓存避坑

  • 云顶yd12302
  • 2019-03-25
  • 240人已阅读
简介MyBatis一级缓存(MyBaits称其为LocalCache)无法关闭,但是有两种级别可选:packageorg.apache.ibatis.session;/***

MyBatis 一级缓存(MyBaits 称其为 Local Cache)无法关闭,但是有两种级别可选:

package org.apache.ibatis.session;/** * @author Eduardo Macarron */public enum LocalCacheScope { SESSION, //session 级别的缓存 STATEMENT //statement 级别的缓存}

 

1)session 级别的缓存

在同一个 sqlSession 内,对同样的查询将不再查询数据库,直接从缓存中。

验证代码:

public static void main(String[] args) throws IOException { InputStream inputStream = new ClassPathResource("mybatis.xml").getInputStream(); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); SqlSession sqlSession = sqlSessionFactory.openSession(); UserDao mapper = sqlSession.getMapper(UserDao.class); System.out.println(mapper.get(1L)); System.out.println("-------------------"); System.out.println(mapper.get(1L));}

输出:

 

日志输出可以看到,第一次查询通过数据库查询,第二次则没有,直接通过缓存读取。

 

:这种缓存策略有一个坑,在服务集群时就会出现问题。

假设现在有一个服务集群,有两个节点。

首先,两个节点都进行了同样的查询,两个节点都有自己的一级缓存,后续同样的查询,两个节点将不再查询数据库。

如果此时节点 1 执行了 update 语句,那么节点 1 的一级缓存会被刷新,而节点 2 的一级缓存不会改变。

 

2)statement 级别的缓存

避坑: 为了避免这个问题,可以将一级缓存的级别设为 statement 级别的,这样每次查询结束都会清掉一级缓存。MyBatis 源码如下:

 

在 MyBatis 的配置文件中,添加以下配置:

 

 验证代码和上面的一样不变。

输出:

可以看到,即使是同样的查询,每次查询都是直接读取数据库了。

避坑完毕。

 

缓存是不可能不要缓存的,这个时候,就需要使用缓存中间件了,由缓存中间件管理缓存。

 

文章评论

Top