http://blog.csdn.net/weixin_36380516/article/details/73194758

先说缓存,合理使用缓存是优化中最常见的,将从数据库中查询出来的数据放入缓存中,下次使用时不必从数据库查询,而是直接从缓存中读取,避免频繁操作数据库,减轻数据库的压力,同时提高系统性能。

一级缓存

一级缓存是SqlSession级别的缓存。在操作数据库时需要构造sqlSession对象,在对象中有一个数据结构用于存储缓存数据。不同的sqlSession之间的缓存数据区域是互相不影响的。也就是他只能作用在同一个sqlSession中,不同的sqlSession中的缓存是互相不能读取的。

一级缓存的工作原理:

用户发起查询请求,查找某条数据,sqlSession先去缓存中查找,是否有该数据,如果有,读取;

如果没有,从数据库中查询,并将查询到的数据放入一级缓存区域,供下次查找使用。

但sqlSession执行commit,即增删改操作时会清空缓存。这么做的目的是避免脏读。

如果commit不清空缓存,会有以下场景:A查询了某商品库存为10件,并将10件库存的数据存入缓存中,之后被客户买走了10件,数据被delete了,但是下次查询这件商品时,并不从数据库中查询,而是从缓存中查询,就会出现错误。

既然有了一级缓存,那么为什么要提供二级缓存呢?

二级缓存是mapper级别的缓存,多个SqlSession去操作同一个Mapper的sql语句,多个SqlSession可以共用二级缓存,二级缓存是跨SqlSession的。二级缓存的作用范围更大。

还有一个原因,实际开发中,MyBatis通常和Spring进行整合开发。Spring将事务放到Service中管理,对于每一个service中的sqlsession是不同的,这是通过mybatis-spring中的org.mybatis.spring.mapper.MapperScannerConfigurer创建sqlsession自动注入到service中的。 每次查询之后都要进行关闭sqlSession,关闭之后数据被清空。所以spring整合之后,如果没有事务,一级缓存是没有意义的。

二级缓存

二级缓存原理:

二级缓存是mapper级别的缓存,多个SqlSession去操作同一个Mapper的sql语句,多个SqlSession可以共用二级缓存,二级缓存是跨SqlSession的。

UserMapper有一个二级缓存区域(按namespace分),其它mapper也有自己的二级缓存区域(按namespace分)。每一个namespace的mapper都有一个二级缓存区域,两个mapper的namespace如果相同,这两个mapper执行sql查询到数据将存在相同的二级缓存区域中。

开启二级缓存:

1,打开总开关

在MyBatis的配置文件中加入:

2,在需要开启二级缓存的mapper.xml中加入caceh标签

3,让使用二级缓存的POJO类实现Serializable接口

public class User implements Serializable {}

测试一下

@Test

public void testCache2() throws Exception {

SqlSession sqlSession1 = sqlSessionFactory.openSession();

SqlSession sqlSession2 = sqlSessionFactory.openSession();

UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class);

User user1 = userMapper1.findUserById(1);

System.out.println(user1);

sqlSession1.close();

UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class);

User user2 = userMapper2.findUserById(1);

System.out.println(user2);

sqlSession2.close();

}

输出结果:

DEBUG [main] - Cache Hit Ratio [com.iot.mybatis.mapper.UserMapper]: 0.0

DEBUG [main] - Opening JDBC Connection

DEBUG [main] - Created connection 103887628.

DEBUG [main] - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@631330c]

DEBUG [main] - ==>  Preparing: SELECT * FROM user WHERE id=?

DEBUG [main] - ==> Parameters: 1(Integer)

DEBUG [main] - <==      Total: 1

User [id=1, username=张三, sex=1, birthday=null, address=null]

DEBUG [main] - Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@631330c]

DEBUG [main] - Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@631330c]

DEBUG [main] - Returned connection 103887628 to pool.

DEBUG [main] - Cache Hit Ratio [com.iot.mybatis.mapper.UserMapper]: 0.5

User [id=1, username=张三, sex=1, birthday=null, address=null]

我们可以从打印的信息看出,两个sqlSession,去查询同一条数据,只发起一次select查询语句,第二次直接从Cache中读取。

前面我们说到,Spring和MyBatis整合时, 每次查询之后都要进行关闭sqlSession,关闭之后数据被清空。所以spring整合之后,如果没有事务,一级缓存是没有意义的。那么如果开启二级缓存,关闭sqlsession后,会把该sqlsession一级缓存中的数据添加到namespace的二级缓存中。这样,缓存在sqlsession关闭之后依然存在。

总结:

对于查询多commit少且用户对查询结果实时性要求不高,此时采用mybatis二级缓存技术降低数据库访问量,提高访问速度。

但不能滥用二级缓存,二级缓存也有很多弊端,从MyBatis默认二级缓存是关闭的就可以看出来。

二级缓存是建立在同一个namespace下的,如果对表的操作查询可能有多个namespace,那么得到的数据就是错误的。

举个简单的例子:

订单和订单详情,orderMapper、orderDetailMapper。在查询订单详情时我们需要把订单信息也查询出来,那么这个订单详情的信息被二级缓存在orderDetailMapper的namespace中,这个时候有人要修改订单的基本信息,那就是在orderMapper的namespace下修改,他是不会影响到orderDetailMapper的缓存的,那么你再次查找订单详情时,拿到的是缓存的数据,这个数据其实已经是过时的。

根据以上,想要使用二级缓存时需要想好两个问题:

1)对该表的操作与查询都在同一个namespace下,其他的namespace如果有操作,就会发生数据的脏读。

2)对关联表的查询,关联的所有表的操作都必须在同一个namespace。

http://www.360doc.com/content/15/1205/07/29475794_518018352.shtml

https://www.cnblogs.com/cuibin/articles/6827116.html

http://blog.csdn.net/u013036274/article/details/55815104

java mysql 二级缓存_深入理解MyBatis中的一级缓存与二级缓存相关推荐

  1. java的lookup方法_深入理解Spring中的Lookup(方法注入)

    前言 本文主要给大家介绍了关于Spring中Lookup(方法注入)的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍: 在使用Spring时,可能会遇到这种情况:一个单例的Be ...

  2. Mybatis 中的一级缓存与二级缓存

    一,Mybatis中为什么要有缓存   缓存的意义是将用户经常查询的数据放入缓存(内存)中去,用户去查询数据的时候就不需要从磁盘(关系型数据库)中查询,直接从缓存中查询,从而提高了查询效率,解决了高并 ...

  3. mybatis 原理_深入理解MyBatis原理 MyBatis数据源与连接池

    点击上方"程序开发者社区"关注,选择"设为星标" 第一时间送达实用干货 对于ORM框架而言,数据源的组织是一个非常重要的一部分,这直接影响到框架的性能问题.本文 ...

  4. MyBatis中的一级缓存和二级缓存介绍

    先说缓存,合理使用缓存是优化中最常见的,将从数据库中查询出来的数据放入缓存中,下次使用时不必从数据库查询,而是直接从缓存中读取,避免频繁操作数据库,减轻数据库的压力,同时提高系统性能. 一级缓存 一级 ...

  5. mybatis 批量提交清除缓存_重学Mybatis(三)-------缓存 (含面试题)

    博主将会针对Java面试题写一组文章,包括J2ee,SQL,主流Web框架,中间件等面试过程中面试官经常问的问题,欢迎大家关注.一起学习,一起成长,文章底部有面试题. mybatis的一级缓存 myb ...

  6. 【mybatis】Mybatis中的一级、二级缓存

    [mybatis]简介 [mybatis]mybatis & mybatis-plus & hibernate的区别 [mybatis]核心成员分析 [mybatis]Mybatis的 ...

  7. 取消对 null 指针“l”的引用。_彻底理解链表中为何使用二级指针或者一级指针的引用...

    在用c/c++写数据结构程序时,链表和二叉树中经常需要用到二级指针或者一级指针的引用,那么什么时候用什么时候不用呢? 先看一个简单的c++链表操作程序: [cpp] view plaincopy/* ...

  8. java 线程的构造函数_深入理解Thread构造函数

    本文参考汪文君著:Java高并发编程详解. 1.线程的命名 在构造现成的时候可以为线程起一个名字.但是我们如果不给线程起名字,那线程会有一个怎样的命名呢? 这里我们看一下Thread的源代码: pub ...

  9. java mysql点赞功能_点赞功能与redis

    前言 点赞其实是一个很有意思的功能.基本的设计思路有大致两种, 一种自然是用mysql等 数据库直接落地存储, 另外一种就是利用点赞的业务特征来扔到redis(或memcache)中, 然后离线刷回m ...

最新文章

  1. Xcode8 及iOS10适配问题汇总
  2. matlab1信号的单边z变换:,实验二 离散时间信号与系统的Z变换分析
  3. python sklearn.model_selection.ShuffleSplit()函数的用法
  4. Binary Formats in JavaScript: Base64, Deflate, and UTF8
  5. .NET高级代码审计(第三课)Fastjson反序列化漏洞
  6. java 去除 quot,JAVA去除web页面传入后台的特殊字符工具类 | 学步园
  7. 去大公司和小公司实习对比
  8. 数据库系统工程师5天修炼_程序员逆袭之路,5年IT人生从电脑装机到技术大神,人生不认输...
  9. acm的ubuntu (ubuntu16.04 安装指南,chrome安装,vim配置,git设置和github,装QQ)
  10. 一步一坑学android之安装andriod studio(andriod studio3.0)
  11. activiti 定时任务和线程池
  12. 支付宝“跑路”,一亿用户服务彻底关停!
  13. 静态路由实验:Dynagen-Dynamips + WinPcap + SecureCRT
  14. 七夕情人节表白网页代码大全(浪漫的html表白源代码)
  15. GEE-Python遥感大数据分析、管理与可视化
  16. 山东理工大学ACM平台题答案关于C语言 1228 两数组最短距离
  17. 老毛子(华硕)固件ipv6及dmz主机设置
  18. 【Java接口】限制App登录次数
  19. 网络舆情信息传播动态监测查询方法
  20. 极致、简约、专业、优质的在线简历

热门文章

  1. Mysql学习总结(2)——Mysql超详细Window安装教程
  2. 打印中间空了一个的菱形_简单空实心图形打印|Python练习系列[3]
  3. python输入错误提示再次输入_Python实现用户登录并且输入错误三次后锁定该用户...
  4. html绘制静态图表,怎样用JavaScript和HTML5 Canvas绘制图表
  5. au如何关闭预览编辑器_在线IDE开发入门之从零实现一个在线代码编辑器
  6. k8s与监控--从telegraf改造谈golang多协程精确控制
  7. 六个细节改变提升 Android L 用户体验
  8. Swift数据类型(五)
  9. Selenium中WebDriver的close()和quit()
  10. java的多线程机制(文字描述区别)