`
liulanghan110
  • 浏览: 1077818 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

mybatis缓存

阅读更多
MyBatis缓存有两种:一级缓存和二级缓存。
 
一级缓存(local cache),即本地缓存,作用域默认为session。当 Session flush 或 close 之后,该Session中的所有 Cache 就将清空。
本地缓存不能被关闭,可以调用clearCache()来清空本地缓存,或者改变缓存的作用域。
 不能被关闭的原因如下(没看大懂):
By default local cache data is used for the whole session duration. This cache is needed to resolve circular references and to speed up repeated nested queries, so it can never be completely disabled but you can configure the local cache to be used just for the duration of an statement execution by setting localCacheScope=STATEMENT.
 
在SELECT语句中配置刷新缓存,如下:
<select id="aaa" parameterType="string" resultType="integer"  flushCache="true"> 
 
 
在mybatis3.1之后,可以配置本地缓存的作用域。在mybatis.xml中配置,如下:
<setting name="localCacheScope" value="SESSION"/>           作用域为SESSION,这位默认值。
<setting name="localCacheScope" value=" STATEMENT "/>    作用域为STATEMENT,即作用域为SQL。
 
 
二级缓存(second level cache),作用域默认为Mapper(Namespace)。
二级缓存可以被配置为打开或者关闭,默认为关闭,在mybatis.xml中配置。
<setting name="cacheEnabled" value="true"/>
当全局的二级缓存(setting中配置)设置为关闭时可以在Mapper XML中配置单个mapper的二级缓存为打开,配置如下:
<cache />
 
当全局的二级缓存(setting中配置)设置为打开时,mapper中这个配置无效,即mapper中配置为关闭该mapper的二级缓存也是打开。
如果想对某条SQL单独对待,可以在SELECE语句中配置useCache,配置如下:
<select id="aaa" parameterType="string" resultType="integer" useCache="false"> 
 
 
当某一个作用域(一级缓存Session/二级缓存Namespaces)的进行了 C/U/D 操作后,默认该作用域下所有 select 中的缓存将被clear。
 
当执行一条查询SQL时,
流程为: 从二级缓存中进行查询 -> [如果缓存中没有,委托给 BaseExecutor] -> 进入一级缓存中查询 -> [如果也没有] -> 则执行 JDBC 查询。
 
    例子:
 
 @Transactional
    public void test() {
        System.out.println(depotService.get(252L).getName());
        DepotDto dto = new DepotDto();
        dto.setId(252l);
        dto.setName("test");
        depotService.update(dto);
        System.out.println(depotService.get(252L).getName());
    }
 
输出为:
张江站
test
 
上面的代码test1和test2是一个事务,当执行test1时:
查询站点,保存值到一级缓存(test1),保存值到二级缓存(mapper)。
更新站点的name,刷新一级缓存(test1), 刷新二级缓存(mapper)。
再查询站点,先看二级缓存,没有;再看一级缓存,没有,最后从数据库中查询。所以得出的是数据库中的最新值。
 
 
但当将 depotService.update 方法事务属性配置为REQUIRES_NEW时,相当于有事务test1和事务test2。
输出为:
张江站
张江站
 
 
当执行test1时:
查询站点,保存值到一级缓存(test1),保存值到二级缓存(mapper)。
更新站点的name,刷新一级缓存(test2), 刷新二级缓存(mapper)。此时在test2内部,刷新的是test2的一级缓存,所以
test1的一级缓存还在。
再查询站点,先看二级缓存(mapper),没有;再看一级缓存(test1)(此时在test1事务内部,查找的是test1的一级缓存),
有,则返回值。所以得出的不是数据库中的最新值。
 
如果这时将mapper的get语句配置成这样。
<select id="get" parameterType="java.lang.Long"  resultMap="depotResultMap" flushCache="true"> 
 
输出为:
张江站
test
 
     在mybatis3.1之后,。可以在mybatis.xml中配置得到一样的效果。
 
    最后,强烈推荐阅读http://www.iteye.com/topic/1112327这篇文章。

 另外,个人觉得由于二级缓存作用域是namespace,namespace一般对应一个表,当两个表关联查询时,不知道将SQL放入哪个namespace中。所以配置二级缓存开启的SQL最好是和基础表关联(不常更变的数据)。两个业务表关联的SQL,最好不配置二级缓存开启。

分享到:
评论
12 楼 mos5100 2015-04-23  
634564
11 楼 liulanghan110 2014-04-04  
ForgiDaved 写道
   找到了,读了下源码,发现存入缓存的是一个叫做CacheKey的玩意:debug了下是这个样子的:1236890589:1642688492:yunnex.dgtw.mapper.AnnouncementMapper.getListByParams:0:2147483647:select * from announcement order by send_time desc limit 0 ,11,会把实际生成的sql语句拼接起来,我还以为只是根据查询语句的id来定义key。感谢楼主的谆谆教诲

现在才看到消息。。。确实是你上面说的意思,不过你看了源码了,呵呵
10 楼 ForgiDaved 2014-04-02  
   找到了,读了下源码,发现存入缓存的是一个叫做CacheKey的玩意:debug了下是这个样子的:1236890589:1642688492:yunnex.dgtw.mapper.AnnouncementMapper.getListByParams:0:2147483647:select * from announcement order by send_time desc limit 0 ,11,会把实际生成的sql语句拼接起来,我还以为只是根据查询语句的id来定义key。感谢楼主的谆谆教诲
9 楼 ForgiDaved 2014-04-02  
liulanghan110 写道
ForgiDaved 写道
liulanghan110 写道
ForgiDaved 写道
   楼主对mybatis动态sql下的二级缓存实现有啥思路?

个人觉得由于二级缓存作用域是namespace,namespace一般对应一个表,当两个表关联查询时,不知道将SQL放入哪个namespace中。所以配置二级缓存开启的SQL最好是和基础表关联(不常更变的数据)。两个业务表关联的SQL,最好不配置二级缓存开启。

    可能是我没有表述请求,我所说的动态sql是指sql里面带有if、choose等条件判断的sql的二级缓存


带判断条件的SQL,条件不同SQL不同,查询结果也不同。动态sql可以说是多个普通SQL,会缓存多个结果。你需要如何特殊处理它?

    你的意思是缓存的key是执行的SQL语句么?条件不同生成的执行sql不同,则缓存的key值不同?
8 楼 liulanghan110 2014-04-01  
ForgiDaved 写道
liulanghan110 写道
ForgiDaved 写道
   楼主对mybatis动态sql下的二级缓存实现有啥思路?

个人觉得由于二级缓存作用域是namespace,namespace一般对应一个表,当两个表关联查询时,不知道将SQL放入哪个namespace中。所以配置二级缓存开启的SQL最好是和基础表关联(不常更变的数据)。两个业务表关联的SQL,最好不配置二级缓存开启。

    可能是我没有表述请求,我所说的动态sql是指sql里面带有if、choose等条件判断的sql的二级缓存


带判断条件的SQL,条件不同SQL不同,查询结果也不同。动态sql可以说是多个普通SQL,会缓存多个结果。你需要如何特殊处理它?
7 楼 ForgiDaved 2014-04-01  
liulanghan110 写道
ForgiDaved 写道
   楼主对mybatis动态sql下的二级缓存实现有啥思路?

个人觉得由于二级缓存作用域是namespace,namespace一般对应一个表,当两个表关联查询时,不知道将SQL放入哪个namespace中。所以配置二级缓存开启的SQL最好是和基础表关联(不常更变的数据)。两个业务表关联的SQL,最好不配置二级缓存开启。

    可能是我没有表述请求,我所说的动态sql是指sql里面带有if、choose等条件判断的sql的二级缓存
6 楼 liulanghan110 2014-04-01  
ForgiDaved 写道
   楼主对mybatis动态sql下的二级缓存实现有啥思路?

个人觉得由于二级缓存作用域是namespace,namespace一般对应一个表,当两个表关联查询时,不知道将SQL放入哪个namespace中。所以配置二级缓存开启的SQL最好是和基础表关联(不常更变的数据)。两个业务表关联的SQL,最好不配置二级缓存开启。
5 楼 ForgiDaved 2014-03-31  
   楼主对mybatis动态sql下的二级缓存实现有啥思路?
4 楼 liulanghan110 2014-03-31  
Joeyfihs_1020 写道
请教一下,mybatis的二级缓存是根据namespace来划分cache的域的,也是就必须要在同一个namespace下面的才会在U/C/D之后对select刷新。
如果用mybatis-generator来自动生成mapper文件。在我做的项目中,通常这些生成的文件都没有修改。因为如果改表的话,直接重新生成文件即可,不用考虑merge的问题。
如果有一个select和很多基础表有关的话,如果分配这个select在那一个namespace,或者说有其他的方法可以解决这个这个cache的刷新?


如果该语句和很多表关联,select确实放哪都不好,建议关闭该SQL的二级缓存
3 楼 liulanghan110 2014-03-31  
ForgiDaved 写道
  mybatis的二级缓存默认是关闭的吧。请参考官方网站的doc

对,默认是关闭的
2 楼 ForgiDaved 2014-03-19  
  mybatis的二级缓存默认是关闭的吧。请参考官方网站的doc
1 楼 Joeyfihs_1020 2013-10-18  
请教一下,mybatis的二级缓存是根据namespace来划分cache的域的,也是就必须要在同一个namespace下面的才会在U/C/D之后对select刷新。
如果用mybatis-generator来自动生成mapper文件。在我做的项目中,通常这些生成的文件都没有修改。因为如果改表的话,直接重新生成文件即可,不用考虑merge的问题。
如果有一个select和很多基础表有关的话,如果分配这个select在那一个namespace,或者说有其他的方法可以解决这个这个cache的刷新?

相关推荐

    Mybatis缓存机制案例

    Mybatis缓存机制是数据库操作中的重要组成部分,它能够提高数据访问效率,减少对数据库的重复查询。在Mybatis中,缓存分为一级缓存和二级缓存,这两种缓存各有其特点和应用场景。 一级缓存是SqlSession级别的缓存,...

    MyBatis缓存(一级缓存、二级缓存)

    缓存是MyBatis性能优化的重要手段,分为一级缓存和二级缓存。在这篇文章中,我们将深入探讨这两个级别的缓存机制及其工作原理。 **一级缓存** 一级缓存是SqlSession级别的缓存,也称为局部缓存。当你执行一个查询...

    Mybatis缓存测试示例

    在这个“Mybatis缓存测试示例”中,我们将深入探讨Mybatis的缓存机制,以及如何在实际项目中进行测试。 Mybatis 的缓存分为一级缓存和二级缓存。一级缓存是SqlSession级别的,同一SqlSession内的多次相同查询会复用...

    Mybatis系列教程Mybatis缓存共17页.pdf

    本教程“Mybatis系列教程Mybatis缓存共17页”旨在深入解析Mybatis的缓存功能。 在Mybatis中,缓存分为一级缓存和二级缓存。一级缓存是SqlSession级别的,同一个SqlSession内的多次相同查询会复用第一次查询的结果,...

    Mybatis缓存开源架构源码2021.pdf

    在这篇文档《Mybatis缓存开源架构源码2021》中,很可能会深入探讨这两级缓存的工作原理和实现。 首先,一级缓存是 SqlSession 级别的,基于 HashMap 实现。当我们在一个 SqlSession 中执行了查询操作,结果会被缓存...

    mybatis+redis缓存配置

    #### 一、MyBatis缓存机制概述 在MyBatis中,缓存是一项重要的性能优化措施。它能够显著减少数据库的访问次数,提高应用程序的响应速度。MyBatis提供了两种级别的缓存支持:一级缓存和二级缓存。 - **一级缓存**:...

    mybatis 缓存的简单配置

    标题 "mybatis 缓存的简单配置" 涉及的是MyBatis框架中的缓存机制,这是一个关键特性,用于提升数据库操作的效率。MyBatis的缓存分为一级缓存和二级缓存,它们各自有不同的作用和实现方式。 一级缓存是SqlSession...

    MyBatis缓存机制深度解剖[收集].pdf

    通过对MyBatis缓存机制的深入理解,开发者可以更有效地利用缓存提升应用性能,同时避免并发控制和数据一致性的问题。通过自定义缓存策略,还可以根据项目需求调整缓存的行为,比如使用更复杂的排除算法或调整缓存...

    Mybatis 缓存原理及失效情况解析

    Mybatis 缓存原理及失效情况解析 Mybatis 缓存是指将经常查询的数据存于内存中,以提高查询效率,解决高并发系统的性能问题。Mybatis 缓存分为一级缓存和二级缓存两种。 一级缓存,也称为本地缓存,指的是...

    【MyBatis学习笔记八】——MyBatis缓存.zip

    本篇笔记将深入探讨MyBatis的缓存机制,包括一级缓存和二级缓存的概念、工作原理、配置与使用。 一级缓存是SqlSession级别的缓存,每当执行一个SQL查询时,如果结果不在缓存中,MyBatis会将其放入一级缓存。当同一...

    mybatis缓存的配置文件

    在处理大量数据时,为了提高性能,MyBatis引入了缓存机制。缓存可以分为一级缓存和二级缓存,它们在不同的范围内存储和复用已查询过的数据,避免重复的数据库访问。 一级缓存是SqlSession级别的,它是默认开启的。...

    MyBatis缓存功能原理及实例解析

    MyBatis缓存功能原理及实例解析 MyBatis缓存功能原理及实例解析是MyBatis框架中非常重要的一部分,它可以极大的提升查询效率,解决高并发系统的性能问题。缓存机制可以将用户经常查询的数据放在缓存(内存)中,...

    MyBatis-05 缓存机制

    本篇文章将详细探讨MyBatis的缓存机制,包括一级缓存和二级缓存,以及如何将MyBatis与第三方缓存EhCache进行整合。 首先,我们来了解一级缓存。一级缓存是SqlSession级别的,也称为本地缓存。当我们在一个...

    mybatis缓存源码解析

    个人学习mybatis源码总结

    缓存处理-mybatis层

    2. 分布式环境下的缓存:在分布式系统中,二级缓存可能导致数据冲突,这时可以考虑使用分布式缓存解决方案,如Redis或Memcached,配合MyBatis的插件实现分布式缓存。 3. 缓存穿透和缓存雪崩:缓存穿透是指查询的...

    MyBatis缓存实现原理及代码实例解析

    MyBatis提供了两种级别的缓存:一级缓存(本地缓存)和二级缓存(全局缓存)。 一级缓存是SqlSession级别的,它默认始终开启。当在一个SqlSession中执行SQL查询时,查询结果会被存储在本地缓存中。如果后续请求相同...

    Mybatis(dao)缓存|mybatis+redis(dao+service)缓存验证

    #### 一、Mybatis缓存机制概述 Mybatis提供了一级缓存和二级缓存两种缓存机制,这两种缓存机制有助于提高数据访问的效率。 **1.1 一级缓存** 一级缓存是在同一个`SqlSession`生命周期内的缓存机制,它基于Per ...

    mybatis二级缓存

    标题中的“mybatis二级缓存”指的是MyBatis框架中的一个重要特性,它是MyBatis缓存机制的一部分,用于提升数据库查询效率。MyBatis一级缓存是SqlSession级别的,而二级缓存则是在整个Mapper配置范围内的全局缓存,...

Global site tag (gtag.js) - Google Analytics