Mybatis的一级缓存和二级缓存,看完不再懵逼

源代码 2024-9-12 22:07:44 115 0 来自 中国
缓存是什么?

缓存着实就是存储在内存中的暂时数据,这里的数据量会比较小,一样平常来说,服务器的内存也是有限的,不大概将全部的数据都放到服务器的内存内里,以是, 只会把关键数据放到缓存中,缓存由于速率快,使用方便而着名!
为什么须要缓存

BS架构内里,用户的全部利用都是对数据库的增编削查,此中查询的利用是最多的,但假如用户想要某个数据时每次都去数据库查询,这无疑会增长数据库的压力,而且获取时间服从也会低沉,以是为了办理这些题目,缓存应用而生,使用了缓存之后,服务器只须要查询一次数据库,然后将数据生存到服务器主机的内存中,以后读取时就直接取内存中的数据,而不须要每次都查数据库,这种方案除了低沉数据库压力之外,还进步了相应速率,简直一箭双雕哇~
哪些数据会放到缓存

通常环境下,都会将那些变革较少且常常用到的数据会放到缓存中,比如像字典、体系参数、有固定值的状态码等等;别的将用户生存到缓存也是一种很好的策略,如许登录的时间就可以极速相应了;
mybatis一级缓存

mybatis 的缓存分为2类,分别是一级缓存和二级缓存,一级缓存是默认开启的,它在一个sqlSession会话内里的全部查询利用都会生存到缓存中,一样平常来说一个哀求中的全部增编削查利用都是在同一个sqlSession内里的,以是我们可以以为每个哀求都有本身的一级缓存,假如同一个sqlSession会话中2 个查询中央有一个 insert 、update或delete 语句,那么之前查询的全部缓存都会清空;
Reader reader = Resources.getResourceAsReader("config/configuration.xml");        //创建数据工厂        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();        SqlSessionFactory sqlSessionFactory = builder.build(reader);        SqlSession sqlSession = sqlSessionFactory.openSession(true);         // 。。。。。。         // 这中央所走的全部查询利用都会举行缓存,一旦关闭sqlSession会话,缓存则会刷新        //开释会话        sqlSession.clearCache();        // 关闭会话        sqlSession.close();一级缓存流程图

[图片上传失败...(image-1956eb-1649686882541)]
我们来试验一把
在mybatis 的配置文件中加入以下配置,开启sql日记,每一个sql代表哀求了一次数据库,如许我们就可以根据sql来判断是否使用了缓存
<settings>        <!--标准的日记工厂实现类,打印sql日记-->        <setting name="logImpl" value="STDOUT_LOGGING"/>    </settings>示例代码
public static void main(String[] args) throws IOException {        // 加载mybatis配置文件        Reader reader = Resources.getResourceAsReader("config/configuration.xml");        //创建数据工厂        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();        SqlSessionFactory sqlSessionFactory = builder.build(reader);        SqlSession sqlSession = sqlSessionFactory.openSession(true);        // 获取mapper接口对象        UserMapper mapper = sqlSession.getMapper(UserMapper.class);        // 查询第一次        User user = mapper.selectByPrimaryKey("3rfrf34r34");        // 第二次查询        User user1 = mapper.selectByPrimaryKey("3rfrf34r34");        System.out.println("两个user对象是否相称:"+(user == user1));        //开释会话        sqlSession.clearCache();        sqlSession.close();    }打印结果
1.png 根据结果可以看到,代码中执行了2次查询, 但现实运行时只查询了一次数据库,第二次获取数据时直接从缓存中读取,而且2次读取的数据都是一样的,到这里,一级缓存就已经见效了;
接下来我们来测试第二种环境 :查询 -> 修改 -> 查询
实例代码
public static void main(String[] args) throws IOException {        // 加载mybatis配置文件        Reader reader = Resources.getResourceAsReader("config/configuration.xml");        //创建数据工厂        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();        SqlSessionFactory sqlSessionFactory = builder.build(reader);        SqlSession sqlSession = sqlSessionFactory.openSession(true);        // 获取mapper接口对象        UserMapper mapper = sqlSession.getMapper(UserMapper.class);        // 查询第一次        User user = mapper.selectByPrimaryKey("3rfrf34r34");        // 修改        mapper.updateByPrimaryKey(user);        // 第二次查询        User user1 = mapper.selectByPrimaryKey("3rfrf34r34");        System.out.println("两个user对象是否相称:"+(user == user1));        //开释会话        sqlSession.clearCache();        sqlSession.close();    }打印结果
控制台打印了三次sql,此中第一个查询和第三个查询是一样的,但是并没有使用缓存,为什么会如许呢?由于每次增编削利用都有大概会改变原来的数据,以是必须刷新缓存;
二级缓存

二级缓存是全局的,也就是说;多个哀求可以共用一个缓存,二级缓存须要手动开启,有2种方式配置二级缓存,

  • 缓存会先放在一级缓存中,当sqlSession会话提交大概关闭时才会将一级缓存刷新到二级缓存中;
  • 开启二级缓存后,用户查询时,会先去二级缓存中找,找不到在去一级缓存中找;
二级缓存流程图

3.png 第一种配置方式

单个mapper配置,主须要在须要开启二级缓存的mapper.xml文件中加入以下配置即可开启
<!-- 开启单个mapper的二级缓存,也叫全局缓存-->  <cache />注意肯定要加到xxMapper.xml的文件内,千万不要加到mybatis 的主配置文件内里了,会报错的
第二种配置方式

全部的mapper都开启二级缓存,在mybatis.xml中加入以下配置即可
<settings>        <!--  开启全部mapper的二级缓存 -->        <!--<setting name="cacheEnabled" value="true" />-->    </settings>示例代码
public static void main(String[] args) throws IOException {        // 加载mybatis配置文件        Reader reader = Resources.getResourceAsReader("config/configuration.xml");        //创建数据工厂        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();        SqlSessionFactory sqlSessionFactory = builder.build(reader);        // 第一个会话        SqlSession sqlSession = sqlSessionFactory.openSession(true);        // 获取会话一的mapper接口对象        UserMapper mapper = sqlSession.getMapper(UserMapper.class);        // 第一次查询        User user = mapper.selectByPrimaryKey("3rfrf34r34");        //开释第一个会话        sqlSession.clearCache();        sqlSession.close();        // 第二个会话        SqlSession sqlSession2 = sqlSessionFactory.openSession(true);        // 获取会话二的mapper接口对象        UserMapper mapper2 = sqlSession2.getMapper(UserMapper.class);        // 第二次查询        User user1 = mapper2.selectByPrimaryKey("3rfrf34r34");        // 开释第二个会话        sqlSession2.clearCache();        sqlSession2.close();    }打印结果
打印结果很显着,2次查询,但是日记表现只查询了一次数据库, 第二次是从缓存中获取的数据,至此,二级缓存已开启!
注意事项


  • 别的,缓存另有以下几种环境须要注意
  • 映射语句文件中的全部 select 语句的结果将会被缓存。
  • 映射语句文件中的全部 insert、update 和 delete 语句会刷新缓存。
  • 缓存会使用迩来最少使用算法(LRU, Least Recently Used)算法来扫除不须要的缓存。
  • 缓存不会定时举行刷新(也就是说,没有刷新隔断)。
  • 缓存会生存列表或对象(无论查询方法返回哪种)的 1024 个引用。
  • 缓存会被视为读/写缓存,这意味着获取到的对象并不是共享的,可以安全地被调用者修改,而不干扰其他调用者或线程所做的潜伏修改。
您需要登录后才可以回帖 登录 | 立即注册

Powered by CangBaoKu v1.0 小黑屋藏宝库It社区( 冀ICP备14008649号 )

GMT+8, 2024-11-22 23:04, Processed in 0.180473 second(s), 35 queries.© 2003-2025 cbk Team.

快速回复 返回顶部 返回列表