mybatis提供了查询缓存功能,用于减轻数据压力,提高数据库性能。mybatis提供了一级缓存和二级缓存,如下图所示:

从上图可以看出:

一级缓存是存在于一个sqlSession中的,而sqlSession就是操作数据库的一个会话对象,在对象中实际存储了一个hashMap的数据结构用于存储缓存数据。不同的sqlSession之间的缓存数据互不影响。Mybatis默认开启一级缓存。

二级缓存是mapper级别的缓存,当多个sqlSession操作同一个mapper配置中的SQL语句时,多个sqlSession可以共用二级缓存,二级缓存是跨sqlSession的。

>一级缓存

mybatis一级缓存的作用域是同一个sqlSession,在同一个sqlSession中两次执行相同的sql语句,第一次执行完毕会将数据库中查询的数据写到缓存(内存),第二次会从缓存中获取数据将不再从数据库查询,从而提高查询效率。当一个sqlSession结束后该sqlSession中的一级缓存也就不存在了。mybatis默认开启一级缓存。

如下图所示:

(1)第一次执行查询id为1的用户的信息操作时,先在缓存中查找,如果没有,则执行数据库查询操作,并将从数据库中查询到的用户数据信息,并放入到一级缓存。mybatis内部存储缓存使用一个HashMap,key为hashCode+sqlId+Sql语句。value为从查询出来映射生成的java对象。

(2)如果sqlSession执行insert、update、delete等操作commit提交后会清空一级缓存,这样做的目的是为了让缓存中存储的数据是最新的信息,避免脏读。

(3)第二次执行查询id为1的用户的信息操作时,先去缓存中查找,如果缓存中有,则直接从缓存中获取用户信息。

测试代码:

@Testpublic void queryUserMapper() throws Exception{Integer userId=1;UserMapper mapper=session.getMapper(UserMapper.class);User user = mapper.queryUserById(userId);System.out.println(user);User user2 = mapper.queryUserById(userId);System.out.println(user2);session.close();}

Debug日志:只有第一次执行时,对数据库发出了sql请求;

DEBUG [main] - ==>  Preparing: select * from user where user_id=?
DEBUG [main] - ==> Parameters: 1(Integer)
DEBUG [main] - <==      Total: 1
User [userId=1, userName=zhangsan, password=123456, roleCode=plain, cname=张三, telphone=17864195335, address=山东济南, isLogin=0]
User [userId=1, userName=zhangsan, password=123456, roleCode=plain, cname=张三, telphone=17864195335, address=山东济南, isLogin=0]

当两次查询中间插入事务操作:

@Testpublic void queryUserMapper() throws Exception{Integer userId=1;UserMapper mapper=session.getMapper(UserMapper.class);User user = mapper.queryUserById(userId);System.out.println(user);User user2=new User(null, "xinxinxiangrong", "1234598", "1", "huang", "1789999999", "山东威海", "0");mapper.insertUser(user2);session.commit();User user3 = mapper.queryUserById(userId);System.out.println(user3);session.close();}

Debug日志:向数据库发出了两次查询sql

DEBUG [main] - ==>  Preparing: select * from user where user_id=?
DEBUG [main] - ==> Parameters: 1(Integer)
DEBUG [main] - <==      Total: 1
User [userId=1, userName=zhangsan, password=123456, roleCode=plain, cname=张三, telphone=17864195335, address=山东济南, isLogin=0]
DEBUG [main] - ==>  Preparing: insert into user values(?,?,?,?,?,?,?,?)
DEBUG [main] - ==> Parameters: null, xinxinxiangrong(String), 1(String), 1234598(String), huang(String), 0(String), 1789999999(String), 山东威海(String)
DEBUG [main] - <==    Updates: 1
DEBUG [main] - Committing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@769e7ee8]
DEBUG [main] - ==>  Preparing: select * from user where user_id=?
DEBUG [main] - ==> Parameters: 1(Integer)
DEBUG [main] - <==      Total: 1
User [userId=1, userName=zhangsan, password=123456, roleCode=plain, cname=张三, telphone=17864195335, address=山东济南, isLogin=0]

注意:在正式开发中,是将mybatis和Spring进行整合开发,事务是在service层进行控制,一个service方法中包含很多mapper方法的调用。

在service方法开始执行时,就会开启事务,在开启事务的过程中就会创建SqlSession对象,因此期间不管是调用哪个mapper的方法,都是走一级缓存,有就从缓存中取,没有就从数据库中查询。方法结束时,事务关闭,同时清空一级缓存。

因此在同一service方法中是走一级缓存,如果是两次调用service方法,不走一级缓存,因为方法结束,SqlSession也就关闭,一级缓存就会被清空。

>二级缓存

在mybatis中允许多个SqlSession对象共享一个缓存区域,只不过这个缓存区域并一定在内存中,也可能是存储硬盘空间内,这个共享区域就是mybatis的二级缓存。mybatis同样适用hashMap这种数据结构来存储二级缓存中保存的数据。 如下图所示:

从上图中可以看出,mybatis的二级缓存是根据mapper配置文件的namespace命名空间进行划分的,相同namespace的查询数据操作放在同一个缓存区中。通常开发中,一个Mapper对应一个功能模块,即用户的查询操作的数据是放在UserMapper的缓存区中,订单查询操作的数据是放在OrderMapper的缓存区中。

如果两个用户的SqlSession会话都是执行同一个UserMapper接口中的方法,并且都去查询用户数据,每次查询都会先从缓存区中查找,如果找不到从数据库中查询,查询到的数据写入到二级缓存。

任何一个用户的SqlSession 执行insert、update、delete等操作commit提交后都会清空该mapper下的二级缓存区域。

在mybatis中二级缓存是默认关闭的,如果要开启mybatis的二级缓存,配置如下:

(1)在SqlMapConfig.xml全局配置文件中加入setting信息:

(2)在需要开启的二级缓存的mapper.xml中加入cache标签:

只要加入cache标签就表示开启二级缓存

二级缓存需要查询结果映射的pojo对象实现java.io.Serializable接口实现序列化和反序列化操作,注意如果存在父类、成员pojo都需要实现序列化接口。因为mybatis实现的二级缓存,数据并不一定存储在内存中,也有可能是其他位置,比如硬盘、网络空间等。

在SqlSession会话中,如果会话没有结束,数据只会存储于一级缓存中,如果此SqlSession的会话结束并且此命名空间的mapper开启了二级缓存,这时数据才会写入到二级缓存中。

测试程序:

@Testpublic void queryUserMapper() throws Exception{Integer userId=1;SqlSession session1=factory.openSession();UserMapper mapper1=session1.getMapper(UserMapper.class);User user1 = mapper1.queryUserById(userId);System.out.println(user1);session1.close();SqlSession session2=factory.openSession();UserMapper mapper2=session2.getMapper(UserMapper.class);User user2 = mapper2.queryUserById(userId);System.out.println(user2);session2.close();}

Debugr日志:仅发起了一次Sql查询

DEBUG [main] - ==>  Preparing: select * from user where user_id=?
DEBUG [main] - ==> Parameters: 1(Integer)
DEBUG [main] - <==      Total: 1
User [userId=1, userName=zhangsan, password=123456, roleCode=plain, cname=张三, telphone=17864195335, address=山东济南, isLogin=0]
DEBUG [main] - Resetting autocommit to true on JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@75329a49]
DEBUG [main] - Closing JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@75329a49]
DEBUG [main] - Returned connection 1966250569 to pool.
DEBUG [main] - Cache Hit Ratio [com.langsin.mapper.UserMapper]: 0.5
User [userId=1, userName=zhangsan, password=123456, roleCode=plain, cname=张三, telphone=17864195335, address=山东济南, isLogin=0]

注意:二级缓存需要查询结果映射的pojo对象实现java.io.Serializable接口实现序列化和反序列化操作,否则报错:

Mybatis高级应用 查询缓存相关推荐

  1. java元婴期(25)----java进阶(mybatis(4)---高级映射查询缓存)

    1.需要用到的数据模型(这是后面高级查询需要用到的实例) 用户表user:          记录了购买商品的用户信息 订单表:orders          记录了用户所创建的订单(购买商品的订单) ...

  2. Mybatis延迟加载和查询缓存

    一.延迟加载 resultMap可以实现高级映射(使用association.collection实现一对一及一对多映射),association.collection具备延迟加载功能. 延迟加载:先 ...

  3. mybatis中的查询缓存

    转载自:https://www.cnblogs.com/zhangzongle/p/6211285.html 查询缓存 Mybatis提供查询缓存,用于减轻数据压力,提高数据库压力. Mybatis提 ...

  4. 【MyBatis框架】查询缓存-二级缓存-整合ehcache

    mybatis整合ehcache ehcache是一个分布式缓存框架. 1.分布缓存 我们系统为了提高系统并发,性能.一般对系统进行分布式部署(集群部署方式) 如图 不使用分布缓存,缓存的数据在各各服 ...

  5. 【MyBatis框架】查询缓存-一级缓存原理

    查询缓存 1.什么是查询缓存 mybatis提供查询缓存,用于减轻数据压力,提高数据库性能. mybaits提供一级缓存,和二级缓存. 缓存模式图如图 一级缓存是SqlSession级别的缓存.在操作 ...

  6. 【MySQL高级】查询缓存、合并表、分区表

    [1] 查询缓存   MySQL的缓存机制简单地说就是缓存SQL语句和查询的结果,如果运行相同的SQL语句,服务器会直接从缓存中取到结果,而不需要再去解析和执行SQL语句.   查询缓存会存储最新数据 ...

  7. MySQL高级-MySQL查询缓存优化

    MySQL查询缓存优化 1 概述 2 操作流程 3 查询缓存配置 4 开启查询缓存 5 查询缓存SELECT选项 6 查询缓存失效的情况 1 概述 开启Mysql的查询缓存,当执行完全相同的SQL语句 ...

  8. 【MyBatis框架】查询缓存-二级缓存原理

    二级缓存原理 1.原理 首先看图 首先开启mybatis的二级缓存. sqlSession1去查询用户id为1的用户信息,查询到用户信息会将查询数据存储到二级缓存中. 如果SqlSession3去执行 ...

  9. 手写自己的MyBatis框架-支持查询缓存

    定义了一个CachingExecutor , 当全局配置中的cacheEnabled=true 时,Configuration 的newExecutor()方法会对SimpleExecutor 进行装 ...

最新文章

  1. c如何正常中断一个运行的线程
  2. [译] Spring 的分布式事务实现-使用和不使用XA — 第三部分
  3. flink批处理访问mysql_Flink 异步IO访问外部数据(mysql篇)
  4. 开发MapReduce程序
  5. 华南理工专科计算机随堂联系,华南理工大学网络教育计算机基础随堂练习第三章...
  6. 使用Angular HTTP client对数据模型进行update操作
  7. partition oracle用法,Oracle partition by 使用说明
  8. mouseup 左键_javascript中mouseup事件丢失的原因与解决办法
  9. [React] 尚硅谷 -- 学习笔记(五)
  10. 位居中国机器学习公有云市场份额第一,华为云 ModelArts 的进阶之路
  11. 关于android的日志输出LogCat
  12. 计算机基础视频教程百度云,计算机应用基础视频教程
  13. LabVIEW编程LabVIEW开发PXI-6704输出大于20mA的电流例程与相关资料
  14. 使用md5对文件去重
  15. c 易语言置入代码6,易语言置入代码 , 谁碰到这种情况_精易论坛
  16. PHP架构师“精简”进阶路线规划
  17. TCP的MTU探测功能
  18. deactivate不能关闭venv
  19. canvas画正六边形
  20. 蓝标智能营销转型之战 ——Oracle Eloqua 市场营销云助力蓝标盈云迎战全渠道营销...

热门文章

  1. 详解varint编码原理
  2. 依赖注入[2]: 基于IoC的设计模式
  3. solidity数据位置-memory,storage和calldata
  4. asp.net mvc中的后台验证
  5. Symmetric Tree (101)
  6. 同步机制之--java之CountDownLatch闭锁
  7. Android之launchMode总结
  8. 使用lambda去重、map排序、按任意时间间隔(小时、半小时、分钟)进行结果统计
  9. 焦虑的互联网人及35岁定律
  10. AQS功能及源码详解