精华内容
下载资源
问答
  • mybatis清除一级缓存的几种方法
    2021-12-09 10:58:28

    1、手动清空

    sqlSession.clearCache()
    

    2、Options注解

    public interface UserMapper{
    	@Options(flushCache= Options.FlushCachePolicy.TRUE)
    	User selectById(@params("id")Integer id)
    }
    
    

    3、调用了修改的方法时,底层直接调用sqlSession.clearCache()一次性全部清空

    4、在setting中关闭一级缓存

    locaCacheScope = STATEMENT
    

    5、手动提交/回滚

    更多相关内容
  • mybatis一级缓存和二级缓存

    千次阅读 2022-04-14 17:29:43
    在分布式的环境中,mybatis的一二级缓存非常危险,二级缓存一定要关闭一级缓存视情况关闭 一级缓存失效的四种情况: sqlSession不同。 sqlSession相同,查询条件不同。因为缓存条件不同,缓存中还没有数据。 sq

    一级缓存

    1、说明

    mybatis默认开启一级缓存,一级缓存的作用域是SqlSession范围的,当在同一个sqlSession中执行两次相同的sql语句时,第一次执行完毕会将数据库中查询的数据写到缓存,第二次查询时会从缓存中获取数据,不再去底层数据库查询,从而提高查询效率。

    在分布式的环境中,mybatis的一二级缓存非常危险,二级缓存一定要关闭,一级缓存视情况关闭

    在这里插入图片描述

    一级缓存失效的四种情况:

    1. sqlSession不同。
    2. sqlSession相同,查询条件不同。因为缓存条件不同,缓存中还没有数据。
    3. sqlSession相同,在两次相同查询条件中间执行过增删改操作。(因为中间的增删改可能对缓存中数据进行修改,所以不能用)
    4. sqlSession相同,手动清空了一级缓存。

    2、关闭方法

    (1)注解形式

    使用注解 @Options(flushCache = Options.FlushCachePolicy.TRUE) 可指定仅仅某个Mapper关闭注解)

    @Options(flushCache = Options.FlushCachePolicy.TRUE)
    @Select("select * from ge_jdbc_datasource where id = #{id,jdbcType=BIGINT} and status = 1")
    @ResultMap("resultMap")
    JdbcDataSource find(Long id);
    

    (2)传入随机数

    比如sql传参random()数值 或者 sql传入当前时间毫秒数,切记一定要从方法形参传过去而不要在sql中拼写,否则无效

    举例说明:下面方式无效

    select id from ge_jdbc_datasource where id = 1 and STATUS = 1 AND NOW()=NOW()
    

    (3)设置 statementType

    mapperselect 标签中设置 statementType=STATEMENT

    statementType的设置有3种:

    1. STATEMENT:直接操作sql,不进行预编译,获取数据
    2. PREPARED:(默认)预处理,参数,进行预编译,获取数据
    3. CALLABLE:执行存储过程————CallableStatement

    (4)设置 flushCache

    mapperselect 标签中设置 flushCache=“true”

    (5)设置 localCacheScope

    全局设置 localCacheScope=STATEMENT

    参考:https://blog.csdn.net/u011649691/article/details/116058056

    2、案例

    我们在 getPaymentById 方法中写了两次查询,并且保证方法内的 sqlSession 是同一个。在两次查询期间对数据进行修改,将 serial=001 修改为 serial=002

    package com.scy.springcloud.service.impl;
    
    import com.scy.springcloud.dao.PaymentDao;
    import com.scy.springcloud.entities.Payment;
    import com.scy.springcloud.service.PaymentService;
    import org.apache.ibatis.session.SqlSession;
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Transactional;
    
    import javax.annotation.Resource;
    import java.util.List;
    
    @Service
    public class PaymentServiceImpl implements PaymentService {
        @Resource
        private PaymentDao paymentDao;
    
        //这里注入的sqlSession是org.mybatis.spring.SqlSessionTemplate
        /*@Resource
        public SqlSession sqlSession;*/
    
        @Resource
        SqlSessionFactory sqlSessionFactory;
    
        @Override
        public Payment getPaymentById2(Long id) {
            //org.apache.ibatis.session.defaults.DefaultSqlSession
            SqlSession sqlSession = sqlSessionFactory.openSession();
            Payment payment = sqlSession.selectOne("getPaymentById", id);
            System.out.println(payment.toString());
            try {
                Thread.sleep(10*1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            Payment payment2 = sqlSession.selectOne("getPaymentById", id);
            System.out.println(payment2.toString());
            sqlSession.close();
            return payment2;
        }
    }
    

    查询1(开启缓存)

    两次查询是同样的,没有改变,说明开启了一级缓存。

    Payment(id=31, serial=001)
    Payment(id=31, serial=001)
    

    查询2(关闭缓存)

    select 标签中加入 flushCache="true" 后,使一级缓存失效。

    <select id="getPaymentById" parameterType="Long" resultMap="BaseResultMap" flushCache="true">
        select * from payment where id = #{id};
    </select>
    

    第二次查询结果变为serial=002,说明一级缓存失效。

    Payment(id=31, serial=001)
    Payment(id=31, serial=002)
    

    二级缓存

    1、说明

    MyBatis的二级缓存是Application级别的缓存,二级缓存的作用域默认为mapper(namespace)

    工作机制:

    1. 一个会话,查询一条数据,这个数据会被放在当前会话的一级缓存中。

    2. 如果会话被关闭了,一级缓存中的数据会被保存到二级缓存。新的会话查询信息就会参照二级缓存。

    3. sqlSession > Employee>employee

      sqlSession >DepartmentMapper=>Department

      不同的namespace查出的数据会放在自己对应的缓存中。

    效果:

    查出的数据首先放在一级缓存中,只有一级缓存被关闭或者提交以后,一级缓存数据才会转移到二级缓存

    2、开启方法

    (1)方式一

    mybatis 的配置文件中进行配置

    <configuration>
    	<settings>
    		<!-- 二级缓存开启 -->
    		<setting name="cacheEnabled" value="true"/>
    	</settings>
    </configuration>
    

    (2)方式二

    application.yml文件中进行配置开启mybatis的二级缓存 mybatis.configuration.cache-enabled=true

    # 开启二级缓存
    mybatis:
      configuration:
        cache-enabled: true
    
    # 开启sql打印(可以方便查看是否使用了缓存)
    logging:
      level:
        com.scy.springcloud.dao: debug
    

    3、开启缓存配置

    开启二级缓存的分开关。

    要加入cache的配置二级缓存才会开启。

    <mapper namespace="com.scy.springcloud.dao.PaymentDao">
        <!-- 开启二级缓存 -->
        <cache eviction="LRU" flushInterval="20000" readOnly="true" size="1024">
        </cache>
    </mapper>
    

    cache 相关属性:

    • eviction: 缓存的回收策略

      • LRU(默认):最近最少使用,移除最长时间不被使用的对象
      • FIFO:先进先出,安对象进入缓存的顺序来移除它们
      • SOFT:软引用,移除基于垃圾回收器的状态和软引用规则的对象
      • WEAK: 弱引用,更积极的移除基于垃圾收集器状态和弱引用规则的对象
    • flushInterval:缓存刷新间隔 缓存多长时间清空一次,默认不清空,设置一个毫秒值

    • readOnly:是否只读 。

      • true:只读,mybatis认为所有从缓存中获取数据的操作都是只读操作,不会修改数据。 mybatis为了加快获取速度,直接会将数据在缓存中的引用交给用户,不安全,但速度快。
      • false:非只读,mybatis觉得获取的数据可能会被修改。会利用序列化&反序列化的技术克隆一份新的数据给你,安全,但速度慢。
    • size:缓存最多存放多少个引用。默认1024。

    • type:指定自定义缓存的全类名,实现Mybatis提供的Cache接口即可。

    注意事项:

    实体对象要 implements Serializable ,否则报错

    public class User implements Serializable{
    }
    

    启动工程,如果出现

    Cache Hit Ratio . # 表示缓存开启了.....
    

    参考:

    Mybatis二级缓存失效及二级缓存使用简介
    https://blog.csdn.net/sao_jie/article/details/119297811

    浅谈一下mybatis中@CacheNamespace和@CacheNamespaceRef的区别以及使用

    https://blog.csdn.net/lovely960823/article/details/111277801

    展开全文
  • mybatis一级缓存分析

    # 本篇文章主要是为了帮助自己总结和加深理解,若能帮助到其他小伙伴也是极好的

    基本介绍

            Mybatis中支持一级缓存和二级缓存,一级缓存是默认开启的并且不能关闭,二级缓存默认关闭,可根据需要进行手动开启,总体来说Mybatis的一二级缓存的最终目的就是为了帮助数据库减轻压力,保证高效高速的查询,提高数据库的瓶颈。


    一级缓存

            一级缓存是基于hashmap的本地缓存,作用域只在session中,当session刷新或关闭后,这个session中所有的cache就会被清空。

            注意 如果使用clearCache以及增、删、改的sql进行操作会导致select缓存被清空。

    命中原则

            mybatis是怎样判断两次select语句是完全相同的查询sql?

            1、statementId

            statementId其实就是select语句标签中的的id,如果两条select的id不同,那么必定不会命中。

    例如图中代码,这是两条相同的select查询语句,先使用getByName01进行查询,再使用getByName02以及相同的参数进行查询,仍然不会进入缓存。

    <select id="getByName01">
        SELECT * FROM `user` WHERE name=#{name}
    <select/>
    
    <select id="getByName02">
        SELECT * FROM `user` WHERE name=#{name}
    <select/>

             2、查询参数

            若两次查询必须使用同一条statementId的sql,并且传入的参数一样,否则无法命中缓存。

            这里要注意的是,mybatis不论你在java代码中使用何种方式进行传参,只要最终sql语句中获取的参数相等就可以判定为是相同的参数。

            我们编写一条根据name查询的select,并且使用Map传参。

    <select id="getByName" parameterType="java.util.Map" resultType="user">
        SELECT * FROM `user` WHERE name=#{name}
    <select/>

             在两次查询中,我们传入两个不同的hashmap参数(只有name会传入sql中),结果会怎样?第二次查询使用缓存还是查询数据库?

    public void test(){
        // 第一次查询
        HashMap param1 = new HashMap();
        param1.put("name","alix");
        param1.put("test",123);
        mapper.getUserByName(param1);
    
        // 第二次查询
        HashMap param2 = new HashMap();
        param2.put("name","alix");
        param1.put("test",321);
        mapper.getUserByName(param2);
    }

            通过测试执行,第二次查询竟然没有去数据库查询,而是读取了第一次查询的缓存,通过查看sql日志我们发现sql编译的结果如图所示。

            ==>>   Preparing:SELECT * FROM user WHERE name=?

            ==>>Parameters:alix(Integer)

            <<==            Total:1

             所以,参数相同指的是最终传递到sql中的参数只要是一样的就可以满足条件。

            3、分页参数

            这里的分页指的是mybatis自带的分页功能,很多人可能不熟悉或者很少使用,因为它是查询出数据库的所有数据到本地进行一个物理分页,而不是直接从数据库获取分页之后的结果,这样的一个操作执行效率很低,非常损耗性能,所以也不推荐使用(这里不做过多说明)。

            4、sql语句

            顾名思义,mybatis要求我们查询时使用的sql语句必须相同。但值得注意的是,这里所说的sql语句必须相同指的是这条语句加上参数最终拼接形成完整的sql文本必须完全一样。

            也就是说在查询时并不会考虑sql语句本身的语义,如下代码所示。

    <select id="getUserByNameInGender">
        <if test="gender == 0">
            SELECT * FROM user WHERE name=#{name}
        </if>
        <if test="gender == 1">
            SELECT * FROM user WHERE 1=1 AND name=#{name}
        </if>
    </select>

            我们知道

                    SELECT * FROM user WHERE 1=1 AND name=#{name}SELECT * FROM user WHERE name=#{name}

                    其实是两个意义完全相同的sql语句,但mybatis并不会考虑这种情况。

    总结

            mybatis的一级缓存在什么时候产生?在什么情况下销毁?

            产生:

                    在使用select标签进行查询时才会产生缓存,如果我们在诸如update标签中使用select语句进行查询并不会产生缓存。

            销毁:

                    一级缓存是维持在同一个sqlsession中的,因此在对sqlsession使用close关闭或commit提交后,缓存就会被清空;

                    在使用sqlsession.rollback()进行回滚时,也会导致缓存被清空;

                    进行update操作也会造成缓存被清空,并且dll语句对查询缓存的影响并不局限于同一张表,就是说在A表进行查询产生缓存,然后对B表进行dll操作同样会使A表的select缓存失效(并且是所有缓存);

                    sqlsession还提供了clearCache()方法,这个方法可以让我们主动的对缓存进行清空;

            经常有提到说mybatis一级缓存可能导致脏读的情况,是否真实?为什么?怎么解决?

            针对mybatis一级缓存可能存在产生脏读的情况,我们可以模拟并发情况下的执行步骤来进行分析;

            

            如果按照图中步骤来看,mybatis一级缓存的确存在可能造成脏读的情况;

            所以在实际开发环境中应该避免使用mybatis缓存,而是使用类似redis这样的第三方插件进行全局缓存的管理;

    补充

            一级缓存的hashmap中key和value分别存的是?

            key:hashcode值 + sqlId + sql语句;

            value:映射结果对象;


    后言

    你好,很高兴认识你

            本次关于 “ mybatis一级缓存 ” 的文章到此完结,若有疑问可以私信与我交流。

            如果你也喜欢编程,如果你也喜欢敲代码,如果你也喜欢技术,欢迎联系~

            我是

                    爱敲代码的小王bro

    展开全文
  • mybatis-coinfig.xml文件添加如下配置: <configuration> <settings> <!...-- 设置一级缓存的作用范围是一条sql语句执行期间,执行完毕清空一级缓存--> <setting name=

    在mybatis-coinfig.xml文件添加如下配置:

    <configuration>
        <settings>
            <!--       关闭二级缓存-->
            <setting name="cacheEnabled" value="false"/>
            <!--       设置一级缓存的作用范围是一条sql语句执行期间,执行完毕清空一级缓存-->
            <setting name="localCacheScope" value="STATEMENT"/>
        </settings>
    </configuration>
    

    关闭二级缓存,设定一级缓存作用范围之后,可以彻底解决mybatis数据脏读问题。

    一级缓存不能彻底关闭,因为mybatis内部的许多功能都是基于一级缓存实现的。

    展开全文
  • MyBatis一级缓存与二级缓存

    千次阅读 2022-02-11 15:12:02
    MyBatis一级缓存是基于数据库会话(SqlSession 对象)的,默认开启。二级缓存是基于全局(nameSpace)的,开启需要配置。 对于 JDBC 操作,如果需要连续请求 id=1 的用户数据,那么就要进行两次的数据库连接,获取...
  • Mybatis 禁用一级缓存

    2021-07-26 16:33:09
    一张数据库中的表:table_name,这张表在开发的过程中对应两个Mapper(比如两个模块:模块a, 模块b),mybatis 默认是开启一级缓存的。现在的情况是我在模块a中用程序修改了table_name中的某个字段值(比如:field原来...
  • mybatis一级缓存和如何关闭

    千次阅读 2021-04-23 15:26:45
    Mybatis默认开启一级缓存关闭或者使一级缓存失效的方法: 1、在mapper的select标签中设置statementType=STATEMENT statementType的设置有3种: STATEMENT:直接操作sql,不进行预编译,获取数据 PREPARED:(默认...
  • 一级缓的作用域是 session(会话),二级缓存是 mapper 级别的缓存,二级缓存相对于一级缓存来说,实现了SqlSession之间缓存数据的共享。
  • Mybatis一级缓存(默认开启) 是SqlSession级别的缓存, 默认开启 Mybatis二级缓存(默认关闭,一般不建议使用) namspace/mapper级别(跨sqlSession)的缓存, 默认关闭
  • 缓存是什么 缓存其实就是存储在内存中的临时数据,这里的数据量会比较小,一般来说,服务器的内存也是有限的,不可能将所有的数据都放到
  • Mybatis中的一级缓存和二级缓存到底缓存了什么,缓存了以后又有什么效果,缓存的数据什么时候会被清空?  一级缓存:它指的是Mybatis中sqlSession对象的缓存,当我们执行查询以后,查询的结果会同时存入到...
  • mybatis禁用一级缓存

    2021-05-12 21:23:05
    localCacheScope默认值是SESSION,此时默认开启一级缓存。 值为statement,就会每次请求读取数据库,不会读缓存
  • Mybatis一级缓存与二级缓存 缓存就是内存中的数据,常常来自对数据库查询结果的保存,使用缓存,我们可以避免频繁的与数据库 进行交互,进而提高响应速度。 Mybatis也提供了对缓存的支持,分为一级缓存和二级缓存...
  • 禁用 MyBatis 一级缓存

    2022-04-08 22:03:57
    MyBatis 一级缓存默认开启,是 session 级别。如果要禁用一级缓存,就要设置为 statement 级别,即: <setting name="localCacheScope" value="SESSION"/> //STATEMENT mybatis: configuration: local-...
  • mybatis一级缓存详解

    2020-12-28 15:44:58
    文章目录1、mybatis一级缓存是什么2、代码示例2.1.结果展示:2.2.现象解析3、有多个SqlSession或者分布式的环境下,数据库写操作会引起脏数据3.1代码如下:3.2结果:4、总结 1、mybatis一级缓存是什么 使用缓存可以...
  • 关于Mybatis关闭一级级缓存

    万次阅读 2018-09-10 15:29:24
    这两天折腾mybatis发现它的缓存内容比较不和谐,原因是底层架构会考虑到分布式,但是Mybatis的各个SqlSession的默认一级缓存PerpetualCache不会在各SqlSession间共享,同时他存储下来sql语句和查询到的对象集,再第二次...
  • Mybatis一级缓存失效 在MyBatis和Spring整合中,存在MyBatis一级缓存失效的情况。 SqlSessionTemplate是SqlSession的默认实现,在SqlSessionTemplate的构造器中,创建了sqlSession的代理 //成员变量 private ...
  • Mybatis-一级缓存

    2022-04-05 16:54:01
    Mybatis默认开启一级缓存。 执行流程:当同一个会话中执行查询时,会先去缓存查找以该查询条件为键的值,如存在则缓存命中并返回结果,不存在则发送SQL语句给数据库查询。 增删改操作默认清空一级缓存和二级缓存。 ...
  • Mybatis一级缓存和二级缓存详解

    千次阅读 2021-07-31 17:15:59
    注:本笔记是根据尚硅谷的MyBatis视频记录的 ...关于Mybatis一级缓存和二级缓存执行顺序具体可参考:Mybatis一级缓存和二级缓存执行顺序  Mybatis整合第三方缓存步骤具体可参考:Myb...
  • 问题:为什么有缓存 mybatis默认开启一级缓存 什么场景下必须需要关闭一级缓存 ...关闭一级缓存方法(针对使用MyBatis场景) 第一种:xml形式(关闭所有一级缓存) <settings> <setting name="cacheEnable
  • mybatis 一级缓存和二级缓存

    千次阅读 2022-04-05 22:13:22
    配置mybatis maven: <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> &...
  • mybatis一级缓存

    千次阅读 2018-10-19 00:36:11
    mybatis中提供有一级缓存 和 二级缓存,这里记录一下一级缓存 一级缓存mybatis中默认开启) SqlSession级别的缓存,操作数据库时需要构造SQLSession对象, 在对象中有一个数据结构(HashMap)用于存储缓存数据,...
  • Mybatis支持缓存,默认情况下是开启的一级缓存一级缓存是SqlSession级别,缓存的是SqlSession对象。在SQL语句、参数都相同的情况下,我们使用同一个SqlSession对象调用同一个Mapper方法的时候,只需要执行一次SQL...
  • Mybatis一级缓存和二级缓存详解

    千次阅读 多人点赞 2018-11-19 19:11:59
    注:本笔记是根据尚硅谷的MyBatis视频记录的 对于任何一个持久层框架,都有缓存机制;... 两个关于mybatis缓存额外的链接: ...关于Mybatis一级缓存和二级缓存执行顺序具体可参考:Mybatis一级缓存和二级缓存执行...
  • Java面试题 Mybatis一级缓存 和 二级缓存的区别? 两者区别:一级缓存的作用域是在SqlSession中,二级缓存的作用域是针对mapper做缓存。 一级缓存(本地缓存): 一级缓存是框架默认为我们开启的,我们不需要做任何...
  • MyBatis的缓存1.MyBatis一级缓存2.MyBatis的二级缓存3.二级缓存的相关配置4.MyBatis缓存查询的顺序5.整合第三方缓存EHCache(了解)5.1添加依赖5.2.各个jar包的功能5.3.创建EHCache的配置文件ehcache.xml5.4.设置...
  • Mybatis一级缓存是指Session缓存。一级缓存的作用域默认是SqlSession。Mybatis默认开启一级缓存。 在同一个SqlSession中,执行相同的查询SQL,第一次会去数据库进行查询,并写到缓存中;第二次以后则直接去一级...
  • Mybatis一级缓存

    千次阅读 2022-03-20 16:35:50
    什么是缓存: ...Mybatis中的缓存:系统默认定义了两级缓存:一级缓存和二级缓存 - 默认情况下,只有一级缓存开启,(SqlSession级别的缓存,也称为本地缓存) - 二级缓存需要手动开启和配置,基

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 22,248
精华内容 8,899
关键字:

mybatis关闭一级缓存