• 首页
  • 栏目
  • ERP
  • SpringBoot整合Mybatis-Plus 实战之Mybatis-Plus的一级缓存、二级缓存详解

SpringBoot整合Mybatis-Plus 实战之Mybatis-Plus的一级缓存、二级缓存详解

  • 2021-08-05
  • Admin

前言

现在的JAVA行业,貌似已经是SpringBoot + SpringCloud 的天下了,早期的SSH,SSM框架已经老去,与SpringBoot相结合的JPA框架虽然省去了很多的增删改查sql,但是比较笨拙,在面对一些复杂多变的逻辑时常常力不从心,而相对应的Mybatis由于其高度的灵活性受到广大JAVA攻城狮的欢迎。之前整合过了springboot+mybatis,前几天看到一个面试的问一个问题,Mybatis的一级缓存,二级缓存。我想这个应该也是一个重点吧,所以今天决定来详细解读一下神秘的一二级缓存。

先知

  • 一级缓存是SqlSession级别的缓存。在操作数据库时需要构造sqlSession对象,在对象中有一个数据结构(HashMap)用于存储缓存数据。不同的sqlSession之间的缓存数据区域(HashMap)是互相不影响的。 一级缓存是默认开启的不用配置。
  • 二级缓存是mapper级别的缓存,多个SqlSession去操作同一个Mapper的sql语句,多个SqlSession可以共用二级缓存,二级缓存是跨SqlSession的。二级缓存的开启(实体类必须序列化),然后在配置文件里面配置。

MyBatis-plus 配置要点

核心要点1

mybatis-plus 在springboot 中的核心配置如下

  1. mybatis-plus.configuration.cache-enabled=true
  2. mybatis-plus.mapper-locations=classpath*:/mapper/*.xml
  3. mybatis-plus.type-aliases-package=com.sch.app.mybatis.entity
  4. logging.level.com.sch.app.mybatis.mapper= debug

所需依赖 除了基本的springboot依赖外,还有

核心要点2
  1. <dependency>
  2. <groupId>com.baomidougroupId>
  3. <artifactId>mybatis-plus-boot-starterartifactId>
  4. <version>3.3.2version>
  5. dependency>
  6. <dependency>
  7. <groupId>org.springframework.bootgroupId>
  8. <artifactId>spring-boot-starter-cacheartifactId>
  9. dependency>
  10. <dependency>
  11. <groupId>org.projectlombokgroupId>
  12. <artifactId>lombokartifactId>
  13. dependency>
核心要点3
  • mybatis 语句生成 generatorConfig.xml 用它一步生成需要的基本实体类和接口以及mapper文件(resouses目录下)
  1. generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
  2. <generatorConfiguration>
  3. <classPathEntry location="D:\AJava\mysql-connector-java-8.0.16.jar" />
  4. <context id="msqlTables" targetRuntime="MyBatis3">
  5. <plugin type="org.mybatis.generator.plugins.SerializablePlugin">plugin>
  6. <jdbcConnection connectionURL="jdbc:mysql://localhost:3306/alexshi?serverTimezone=GMT%2B8"
  7. driverClass="com.mysql.cj.jdbc.Driver" password="1234" userId="root" >
  8. <property name="nullCatalogMeansCurrent" value="true"/>
  9. jdbcConnection>
  10. <javaTypeResolver>
  11. <property name="forceBigDecimals" value="false" />
  12. javaTypeResolver>
  13. <javaModelGenerator targetPackage="com.sch.app.mybatis.entity" targetProject="SpringbootMybatis\src\main\java">
  14. <property name="enableSubPackages" value="true"/>
  15. <property name="trimStrings" value="true" />
  16. javaModelGenerator>
  17. <sqlMapGenerator targetPackage="mapper" targetProject="SpringbootMybatis\src\main\resources">
  18. <property name="enableSubPackages" value="true"/>
  19. sqlMapGenerator>
  20. <javaClientGenerator type="XMLMAPPER" targetPackage="com.sch.app.mybatis.mapper" targetProject="SpringbootMybatis\src\main\java">
  21. <property name="enableSubPackages" value="true"/>
  22. javaClientGenerator>
  23. <table schema="" tableName="d_dictionary">table>
  24. <table schema="" tableName="d_dictionary_type">table>
  25. <table schema="" tableName="c_resource">table>
  26. <table schema="" tableName="c_role">table>
  27. <table schema="" tableName="c_role_resource">table>
  28. <table schema="" tableName="c_user_online">table>
  29. <table schema="" tableName="c_user">table>
  30. <table schema="" tableName="c_user_role">table>
  31. <table schema="" tableName="test">table>
  32. context>
  33. generatorConfiguration>
在这里插入图片描述

这个 Run Mybatis Generator 可以在eclipse 的插件市场下的

  • 点击执行后生成以下内容

    在这里插入图片描述
image.png

Mybatis-plus 一级缓存的测试

  • 首先一定要开启日志 方便查看效果
logging.level.com.sch.app.mybatis.mapper= debug

com.sch.app.mybatis.mapper 也就是 mapper接口的目录

在这里插入图片描述
  • 测试代码1
  1. @Autowired
  2. private SqlSessionFactory sqlSessionFactory;
  3. @RequestMapping(value = "/testMybatis")
  4. @ResponseBody
  5. public void testMybatis(){
  6. SqlSession sqlSession = sqlSessionFactory.openSession();
  7. TestMapper testMapper = sqlSession.getMapper(TestMapper.class);
  8. for (int i = 0; i < 3; i++) {
  9. Test selectByPrimaryKey = testMapper.selectByPrimaryKey(5);
  10. log.info("结果:"+ selectByPrimaryKey.getUsername());
  11. }
在这里插入图片描述
  • 结果是
image.png
  • 可以看出,只搜索了一次,第二三次都没有sql打印

  • 测试代码2

  1. @RequestMapping(value = "/testMybatis")
  2. @ResponseBody
  3. public void testMybatis(){
  4. SqlSession sqlSession = sqlSessionFactory.openSession();
  5. TestMapper testMapper = sqlSession.getMapper(TestMapper.class);
  6. for (int i = 0; i < 3; i++) {
  7. Test selectByPrimaryKey = testMapper.selectByPrimaryKey(5);
  8. log.info("结果:"+ selectByPrimaryKey.getUsername());
  9. if (i == 2) {
  10. selectByPrimaryKey.setUsername("刘惜君的妹妹");
  11. testMapper.updateByPrimaryKey(selectByPrimaryKey);
  12. Test selectByPrimaryKey2 = testMapper.selectByPrimaryKey(5);
  13. log.info("更新后的用户名:"+ selectByPrimaryKey2.getUsername());
  14. }
  15. }
  • 打印结果:

    在这里插入图片描述

可见,第一次我加入了更新的代码后再次查询的时候,就又执行了sql语句,说明当执行插入、更新、删除,会清空SqlSession中的一级缓存。只有查询的操作,一级缓存才不会被清除。

Mybatis-plus二级缓存测试

二级缓存的开启除了在配置文件中打开开关 还要在mapper对应开启

在这里插入图片描述
  • 测试代码1
  1. @RequestMapping(value = "/testMybatis2")
  2. @ResponseBody
  3. public void testMybatis2(){
  4. SqlSession openSession1 = sqlSessionFactory.openSession();
  5. SqlSession openSession2 = sqlSessionFactory.openSession();
  6. TestMapper mapper1 = openSession1.getMapper(TestMapper.class);
  7. TestMapper mapper2 = openSession2.getMapper(TestMapper.class);
  8. Test selectByPrimaryKey = mapper1.selectByPrimaryKey(5);
  9. System.out.println(selectByPrimaryKey.getUsername());
  10. openSession1.close();
  11. Test selectByPrimaryKey2 = mapper2.selectByPrimaryKey(5);
  12. System.out.println(selectByPrimaryKey2.getUsername());
  13. openSession2.close();
  14. }
  • 测试结果

    image.png

    由测试结果可知,上述代码第一次查 mapper1.selectByPrimaryKey(5) 的时候执行了sql,然后关闭了第一个session 第二次 用别的sqlseeison 去查没有调用sql,说明了二级换粗和sqlseesion 无关,之和mapper有关。

  • 测试代码2

  1. @RequestMapping(value = "/testMybatis3")
  2. @ResponseBody
  3. public void testMybatis3(){
  4. SqlSession openSession1 = sqlSessionFactory.openSession();
  5. SqlSession openSession2 = sqlSessionFactory.openSession();
  6. SqlSession openSession3 = sqlSessionFactory.openSession();
  7. TestMapper mapper1 = openSession1.getMapper(TestMapper.class);
  8. TestMapper mapper2 = openSession2.getMapper(TestMapper.class);
  9. TestMapper mapper3 = openSession3.getMapper(TestMapper.class);
  10. Test selectByPrimaryKey = mapper1.selectByPrimaryKey(5);
  11. System.out.println(selectByPrimaryKey.getUsername());
  12. openSession1.close();
  13. selectByPrimaryKey.setUsername("刘惜君的姐姐");
  14. mapper2.updateByPrimaryKey(selectByPrimaryKey);
  15. openSession2.commit();
  16. Test selectByPrimaryKey3 = mapper3.selectByPrimaryKey(5);
  17. System.out.println(selectByPrimaryKey3.getUsername());
  18. openSession3.close();
  19. }
  • 打印结果

    在这里插入图片描述

    由此可知,做了更新mapper2.updateByPrimaryKey(selectByPrimaryKey); 之后, 二级缓存才被清空。特性和一级缓存很类似。

初次之外,我们可以通过userCache是来设置具体的语句是否禁用二级缓存

在这里插入图片描述
  • 可见 selectByPrimaryKey 这个查询禁止二级缓存后,两次都从数据库里面查了。

小结

  • 一级缓存是默认开始的,属于会话级别,一个会话做多次做相同查询会开启,如果对查询的数据进行更新,删除等操作时,再次查询会从数据库里查而不用一级缓存。
  • 二级缓存开启最重要,请记住三点,1.配置文件开启mybatis-plus.configuration.cache-enabled=true,2.对应mapper文件开启 3.对应实体类实现Serializable 接口。如果要对某一个sql语句禁用二级缓存,则需要在具体的xml 的sql语句定义处加上 useCache=“false” 。另外记住它和会话无关,和 xml 的 namespace 即具体的mapper 有关。
  • 在mapper的同一个namespace中,如果有其它insert、update、delete操作数据后需要刷新缓存,如果不执行刷新缓存会出现脏读。
  • 设置statement配置中的flushCache=“true” 属性,可以实现二级缓存的刷新,false则可能出现脏读。openSession.clearCache() 可以实现对一级缓存的刷新。

作者: 爱吃早餐的程序员
原文链接:https://blog.csdn.net/weixin_39076203/article/details/110129148

原文:https://blog.csdn.net/l081499/article/details/119412489

联系站长

QQ:769220720