精华内容
下载资源
问答
  • mybatis二级缓存原理

    2021-04-21 23:38:38
    二级缓存设置: //开启二级缓存 <setting name="cacheEnabled" value="true" /> //设置命名空间 <cache/> 每次查询数据,不管有没有自动提交,都需要手动提交。 1、细节太多,增删改操作默认都会...

    二级缓存设置:

    //开启二级缓存
     <setting name="cacheEnabled" value="true" />
     //设置命名空间
      <cache/>
    

    每次查询数据,不管有没有自动提交,都需要手动提交。
    1、细节太多,增删改操作默认都会刷新缓存,清除数据,查询操作除非手动添加,否则不会刷新缓存
    2、commit(boolean),参数的区别是true,一定会提交到数据库,同时会写入缓存。如果为flase,根据是否有增删改操作,有也会提交,否则,不提交,不管有没有提交,都会写入缓存。
    3、SychronizedCache是根据命名空间生成的,一个命名空间只有一个,这里有个责任链,最后写入到PerpetualCache的hashmap中【这里加了锁】
    时序图如下:在这里插入图片描述

    展开全文
  • 在前边的学习中我们大概得了解了mybatis扫描和注入原理和sql的执行过程,还有mybatis插件的原理,在后边我们学习了mybatis的一级缓存原理。那么今天我们主要学习一下myb...

    在前边的学习中我们大概得了解了mybatis扫描和注入原理和sql的执行过程,还有mybatis插件的原理,在后边我们学习了mybatis的一级缓存的原理。那么今天我们主要学习一下mybatis二级缓存吧!

    @Override
      public Listquery(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql)
          throws SQLException {
    只有是select类型的查询才有缓存可言
        Cache cache = ms.getCache();
        if (cache != null) {
    //如果需要就删除当前缓存
          flushCacheIfRequired(ms);
          if (ms.isUseCache() && resultHandler == null) {
            ensureNoOutParams(ms, boundSql);
            @SuppressWarnings("unchecked")
    从缓存中获取,获取不到的话就先填入一个值
            List list = (List) tcm.getObject(cache, key);
            if (list == null) {
              list = delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
    将结果添加到缓存
              tcm.putObject(cache, key, list); // issue #578 and #116
            }
            return list;
          }
        }
        return delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
      }
    

    清空当前缓存

     

    private void flushCacheIfRequired(MappedStatement ms) {
        Cache cache = ms.getCache();
        if (cache != null && ms.isFlushCacheRequired()) {
          tcm.clear(cache);
        }
      }
      
        public Object getObject(Cache cache, CacheKey key) {
        return getTransactionalCache(cache).getObject(key);
      }
    

    如果二级缓存没有那么就添加进去

    private TransactionalCache getTransactionalCache(Cache cache) {
        return transactionalCaches.computeIfAbsent(cache, TransactionalCache::new);
      }
    

    同样我们也发现在执行非select查询的时候,二级缓存会清理

    同样的如果我们使用事务,那么缓存也会在执行结束之后进行释放。

    当发生事务回滚的时候也会将之前加入的缓存key给清理掉

     public void rollback() {
        unlockMissedEntries();
        reset();
      }
    
    
      private void unlockMissedEntries() {
        for (Object entry : entriesMissedInCache) {
          try {
            delegate.removeObject(entry);
          } catch (Exception e) {
            log.warn("Unexpected exception while notifiying a rollback to the cache adapter."
                + "Consider upgrading your cache adapter to the latest version.  Cause: " + e);
          }
        }
      }
    

    分析到这里可能有人就问了,这个sqlsession会回收的时候,这里的cache会不会被回收掉。答案是肯定得,因为executor是sqlsession的私有变量,cachemanager是executor的私有变量。所以二级缓存其实也会在事务提交的时候进行释放。据此我们做一些相关的测试。

    1.关闭一级缓存,开启二级缓存,使用事务。预期会走缓存查询,但是第二次请求会重新建立缓存不会使用第一次请求产生的缓存。

    2.关闭一级缓存,开启二级缓存,不使用事务,预期走缓存,但是第二次请求不会使用缓存。

    但是作者通过实验发现springboot中并没有提供二级缓存相关的开关,也就是说springboot可能已经抛弃了mybatis的二级缓存。毕竟这里边和业务以及项目整合会有脏数据产生。

    通过上述分析,作者并没有发现二级缓存与项目同生共死的作用。反而觉得二级缓存的可用性更低。为什么这么说的原因是每次查询sql,其实都是存sqlsesion池中获取sqlsession,而sqlsession的创建的参数就是executor,executor就是根据我们配置新建的,所以我们的缓存作为executor的私有变量显然也是新的。当然我们还发现cacheexecutor中对事务相关的接口,显然事务操作也会使得二级缓存无效。所以根据作者的分析,二级缓存且不说可能有多么厉害,就这些点个人觉得还没有一级缓存好用。但可能作者的反编译器不够出色,不能看到真相。以后有机会再回过头细细品味吧,就目前来说springboot已经没有二级缓存相关的开启配置了!

    展开全文
  • Mybatis二级缓存

    2021-01-16 00:21:13
    Mybatis的查询缓存总共有两级,我们称之为一级缓存和二级缓存,如图:一级缓存是SqlSession级别的缓存。在操作数据库时需要构造 sqlSession对象,在对象中有一个数据结构(HashMap)用于存储缓存数据。不同的...

    1.缓存介绍

    Mybatis提供查询缓存,如果缓存中有数据就不用从数据库中获取,用于减轻数据压力,提高系统性能。

    Mybatis的查询缓存总共有两级,我们称之为一级缓存和二级缓存,如图:

    d98d6cb61841

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

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

    2.一级缓存

    (1) Mybatis默认开启了一级缓存

    (2)原理图

    d98d6cb61841

    第一次发起查询用户id为1的用户信息,先去找缓存中是否有id为1的用户信息,如果没有,从数据库查询用户信息,将查询到的用户信息存储到一级缓存中。

    如果中间sqlSession去执行commit操作(执行插入、更新、删除),清空SqlSession中的一级缓存,这样做的目的为了让缓存中存储的是最新的信息,避免脏读。

    第二次发起查询用户id为1的用户信息,先去找缓存中是否有id为1的用户信息,缓存中有,直接从缓存中获取用户信息。

    3.二级缓存

    (1) 二级缓存是namespace级别的,默认不开启

    (2) 开启步骤

    1) 

    2) 在mapper.xml中 加入标签 核心参数可不设置 使用默认参数

    (3) 原理图

    d98d6cb61841

    第一次调用mapper下的SQL去查询用户信息。查询到的信息会存到该mapper对应的二级缓存区域内。

    第二次调用相同namespace下的mapper映射文件中相同的SQL去查询用户信息。会去对应的二级缓存内取结果。

    如果调用相同namespace下的mapper映射文件中的增删改SQL,并执行了commit操作。此时会清空该namespace下的二级缓存。

    禁用二级缓存

    默认二级缓存的粒度是Mapper级别的,但是如果在同一个Mapper文件中某个查询不想使用二级缓存的话,就需要对缓存的控制粒度更细。

    在select标签中设置useCache=false,可以禁用当前select语句的二级缓存,即每次查询都是去数据库中查询,默认情况下是true,即该statement使用二级缓存。

    resultType="com.kkb.mybatis.po.User"useCache="true">

    SELECT * FROM user WHERE id = #{id}

    刷新二级缓存

    通过flushCache属性,可以控制select、insert、update、delete标签是否属性二级缓存

    默认设置

    *默认情况下如果是select语句,那么flushCache是false。

    *如果是insert、update、delete语句,那么flushCache是true。

    默认配置解读

    *如果查询语句设置成true,那么每次查询都是去数据库查询,即意味着该查询的二级缓存失效。

    *如果增删改语句设置成false,即使用二级缓存,那么如果在数据库中修改了数据,而缓存数据还是原来的,这个时候就会出现脏读。

    flushCache设置如下:

    resultType="com.kkb.mybatis.po.User"useCache="true"flushCache="true">

    SELECT * FROM user WHERE id =#{id}

    展开全文
  • mybatis二级缓存详解

    2021-03-08 15:23:52
    1 二级缓存简介二级缓存是...看如下图:1.1 整个流程是这样的(不考虑第三方缓存库):当开启二级缓存后,在配置文件中配置这行代码,Mybatis会为SqlSession对象生成Executor对象时,还会生成一个对象:CachingExecuto...

    1  二级缓存简介

    二级缓存是在多个SqlSession在同一个Mapper文件中共享的缓存,它是Mapper级别的,其作用域是Mapper文件中的namespace,默认是不开启的。看如下图:

    26c6bd1e844ff9338acc8c703448a52e.png

    1.1 整个流程是这样的(不考虑第三方缓存库):

    当开启二级缓存后,在配置文件中配置这行代码,Mybatis会为SqlSession对象生成Executor对象时,还会生成一个对象:CachingExecutor,我们称之为装饰者,这里用到了装饰器模式。那么CachingExecutor的作用是什么呢?就是当一个查询请求过来时,CachingExecutor会接到请求,先进行二级缓存的查询,如果没命中,就交给真正的Executor(默认是SimpleExecutor,但是会调用它的父类BaseExecutor的query方法,因为要进行一级缓存的查询)来查询,再到一级缓存中查询,如果还没命中,再到数据库中查询。然后把查询到的结果再返回CachingExecutor,它进行二级缓存,最后再返回给请求方。它是executor的装饰者,增强executor的功能,具有查询缓存的作用。当配置时,请求过来时,BaseExecutor这个抽象类会接到请求,就不进行二级缓存的查询。

    1.2 如何开启二级缓存,分三步:

    一是在配置文件中开启,这是开启二级缓存的总开关,默认是开启状态的:

    二是在Mapper文件中开启缓存,默认是不开启的,需要手动开启:

    三是针对要查询的statement使用缓存,即在节点中配置如下属性:

    useCache="true"

    对于二级缓存有以下说明:

    映射语句文件中的所有 select 语句将会被缓存。

    映射语句文件中的所有 insert,update 和 delete 语句会刷新缓存。

    缓存会使用 Least Recently Used(LRU,最近最少使用的)算法来收回。

    根据时间表(比如 no Flush Interval,没有刷新间隔), 缓存不会以任何时间顺序 来刷新。

    缓存会存储列表集合或对象(无论查询方法返回什么)的 1024 个引用。

    缓存会被视为是 read/write(可读/可写)的缓存,意味着对象检索不是共享的,而 且可以安全地被调用者修改,而不干扰其他调用者或线程所做的潜在修改。

    2 二级缓存存储取出清除过程:

    2.1 二级缓存相关类的讲解:

    在讲解二级缓存的存储取出清除的过程前,先了解下以下几个类:

    2.1.1 TransactionalCache

    TransactionalCache和TransactionalCacheManager是CachingExecutor依赖的两个组件。TransactionalCache实现了Cache接口,作用是保存某个sqlSession的某个事务中需要向某个二级缓存中添加的缓存数据,换句话说就是:某些缓存数据会先保存在这里,然后再提交到二级缓存中。源码如下:

    public class TransactionalCache implementsCache {privateCache delegate;// 底层封装的二级缓存所对应的Cache对象,用到了装饰器模式 如下图1-1private booleanclearOnCommit; // 该字段为true时,则表示当前TransactionalCache不可查询,且提交事务时,会将底层的Cache清空

    // 暂时记录添加都TransactionalCahce中的数据,在事务提交时,会将其中的数据添加到二级缓存中private MapentriesToAddOnCommit;private MapentriesToRemoveOnCommit;publicTransactionalCache(Cache delegate) {this.delegate =delegate;this.clearOnCommit = false;this.entriesToAddOnCommit = new HashMap();this.entriesToRemoveOnCommit = new HashMap();

    }// 查询底层的二级缓存

    @OverridepublicObject getObject(Object key) {if (clearOnCommit) return null; //issue #146

    returndelegate.getObject(key);

    }// 该方法并没有直接将查询的结果对象存储到其封装的二级缓存Cache对象中,而是暂时保存到entriesToAddOnCommit集合中,在事务提交时才会将这些结果从entriesToAddOnCommit集合中添加到二级缓存中

    @Overridepublic voidputObject(Object key, Object object) {

    entriesToRemoveOnCommit.remove(key);

    entriesToAddOnCommit.put(key,newAddEntry(delegate, key, object));

    }

    @OverridepublicObject removeObject(Object key) {

    entriesToAddOnCommit.remove(key);

    entriesToRemoveOnCommit.put(key,newRemoveEntry(delegate, key));returndelegate.getObject(key);

    }

    @Overridepublic voidclear() {

    reset();

    clearOnCommit= true;

    }

    // 事务提交时,先根据clearOnCommit字段的值决定是否清空二级缓存,然后将entriesToAddOnCommit集合中的结果对象保存到二级缓存中public voidcommit() {

    // 事务提交前,清空二级缓存if(clearOnCommit) {

    delegate.clear();

    }else{for(RemoveEntry entry : entriesToRemoveOnCommit.values()) {

    entry.commit();

    }

    }

    // 将entriesToAddOnCOmmit集合中的结果对象添加到二级缓存中for(AddEntry entry : entriesToAddOnCommit.values()) {

    entry.commit();

    }

    reset();

    }private static classAddEntry {privateCache cache;privateObject key;privateObject value;publicAddEntry(Cache cache, Object key, Object value) {this.cache =cache;this.key =key;this.value =value;

    }

    // 将entriesToAddOnCOmmit集合中的结果对象添加到二级缓存中,准确的说是PerpetualCache类的HashMap中public voidcommit() {

    cache.putObject(key, value);

    }

    }private static classRemoveEntry {privateCache cache;privateObject key;publicRemoveEntry(Cache cache, Object key) {this.cache =cache;this.key =key;

    }public voidcommit() {

    cache.removeObject(key);

    }

    }

    }

    79cf2322975b6969b1b50ed3a9b635c7.png

    (图1-1)

    2.1.2 TranactionalCacheManager

    TransactionalCacheManager是用于管理二级缓存对象Cache和TransactionCache的,它定义有transactionalCaches属性,看它的源码部分:

    private Map transactionalCaches = new HashMap();

    2.2 二级缓存的存储和取出过程

    为了说明二级缓存存储取出的整个过程,通过下面demo中代码的执行顺序来分析源码:

    @Testpublic voidselectGoodsTest(){ // 分三步进行源码分析:

    SqlSession sqlSession = getSqlSessionFactory().openSession(true);GoodsDao goodsMapper= sqlSession.getMapper(GoodsDao.class);

    GoodsDao goodsMapper2= sqlSession.getMapper(GoodsDao.class);// 第一步:第一次查询

    goodsMapper.selectGoodsById("1");

    // 第二步:事务提交

    sqlSession.commit();// 第三步:第二次查询

    goodsMapper2.selectGoodsById("1");

    }

    2.2.1 第一步:第一次查询

    当配置二级缓存时,CachingExecutor会接到请求,调用它的query方法:先进行二级缓存的查询,如果没命中,再由BaseExecutor的query方法查询。看源码:

    public Listquery(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql)throwsSQLException {

    // 进行二级缓存的查询

    // 此处的cache就是当mybatis初始化加载mapper映射文件时,如果配置了,就会有该cache对象;下面会对MappedStatement这个类进行分析

    Cache cache=ms.getCache();if (cache != null) {

    //是否需要刷新缓存,默认情况下,select不需要刷新缓存,insert,delete,update要刷新缓存

    flushCacheIfRequired(ms);if (ms.isUseCache() && resultHandler == null) {

    ensureNoOutParams(ms, parameterObject, boundSql);

    @SuppressWarnings("unchecked")

    // 查询二级缓存,二级缓存是存放在PerpetualCache类中的HashMap中的,使用到了装饰器模式 分析此方法

    List list = (List) tcm.getObject(cache, key);if (list == null) {

    // 如果二级缓存没命中,则调用这个方法:这方法中是先查询一级缓存,如果还没命中,则会查询数据库

    list= delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);

    // 把查询出的数据放到TransactionCache的entriesToAddOnCommit这个HashMap中,要注意,只是暂时存放到这里,只有当事务提交后,这里的数据才会真正的放到二级缓存中,后面会介绍这个 分析此方法

    tcm.putObject(cache, key, list);//issue #578. Query must be not synchronized to prevent deadlocks

    }returnlist;

    }

    }

    // 如果不使用缓存,则调用BaseExecutor的方法return delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);

    }

    在这个过程中,有两个方法需要分析:首先是查询二级缓存的方法tcm.getObject,通过跟踪源码最终发现,查询二级缓存是从PerpetualCache类的HashMap中获取数据的,也就是说二级缓存真正存放到了这个地方。另外一个处理查询出的数据tcm.putObject这个方法,这个方法最终是把查询出的数据存放到了TransactionalCache这个类中的HashMap中,以Cache接口的对象为key,查询结果集的映射对象为value。到这里,需要明白一点:在执行查询操作时,查询二级缓存的地点和存储查询数据的地点是不相同的。为什么是这样呢?这就引出了第二步,sqlSession.commit事务提交这个过程。

    2.2.2 第二步:事务提交

    现在我们知道,在第一次查询的时候,会把从数据库中查询的数据放到TransactionCache中,但这里并不是二级缓存存放数据的地方,那么二级缓存的数据什么时候怎么来的呢?这就要分析sqlSession.commit()这个方法了,这个方法就是把之前存放在TransactionCache中的数据提交到二级缓存中,然后清空该数据。通过源码,看下commit方法到底做了哪些事情?进入CachingExecutor的commit方法:

    public void commit(boolean required) throwsSQLException {

    // 清除一级缓存,执行缓存的SQL

    delegate.commit(required);

    // 将存放在TransactionCache中的数据对象提交到PerpetualCache中 进入此方法

    tcm.commit();

    }

    进入TransactionalCacheManager类的commit方法:

    public voidcommit() {

    // 把涉及到的TransactionCache都进行处理:提交到二级缓存,并清空数据for(TransactionalCache txCache : transactionalCaches.values()) {

    txCache.commit(); // 进入该方法 }

    }

    public voidcommit() {if(clearOnCommit) {

    delegate.clear();

    }else{for(RemoveEntry entry : entriesToRemoveOnCommit.values()) {

    entry.commit();

    }

    }

    // 把之前存放到entiriesToAddOnCommit中的数据提交到二级缓存中,具体的说是存放到PerpetualCache类的一个HashMap中for(AddEntry entry : entriesToAddOnCommit.values()) {

    // 进入该方法

    entry.commit();

    }

    //清空该TransactionCache中的数据

    reset();

    }

    进入entry.commit()方法:

    public voidcommit() {

    cache.putObject(key, value); //放到PerpetualCache类中的HashMap中

    }

    到这里二级缓存的原理应该理解个大概了,总结下:当第一次从数据库中查出数据后,会放到TransactionCache类中;当调用sqlSession.commit()方法,进行事务提交后,TransactionCache中的数据会提交到PerpetualCache中,查询二级缓存的数据就是在这个类中,同时,TransactionCache中的数据会清空。

    2.2.3 第三步:第二次查询

    在事务提交之后,数据结果集对象就存放在了二级缓存中,所以第二次查询时,就可以从二级缓存中查询到数据了。进入TransactionalCache的getObject方法:

    @OverridepublicObject getObject(Object key) {if (clearOnCommit) return null; //issue #146

    // 用到了装饰器模式,从PerpetualCache中取出数据

    returndelegate.getObject(key);

    }

    2.3 二级缓存的清除过程

    先运行以下demo:

    public classGoodsDaoTest {private static SqlSessionFactory sqlSessionFactory = null;

    @Testpublic voidselectGoodsTest(){

    SqlSession sqlSession= getSqlSessionFactory().openSession(true);

    SqlSession sqlSession2= getSqlSessionFactory().openSession(true);

    SqlSession sqlSession3= getSqlSessionFactory().openSession(true);

    GoodsDao goodsMapper= sqlSession.getMapper(GoodsDao.class) ;

    GoodsDao goodsMapper2= sqlSession2.getMapper(GoodsDao.class) ;

    GoodsDao goodsMapper3= sqlSession3.getMapper(GoodsDao.class) ;

    goodsMapper.selectGoodsById("1");

    sqlSession.commit();

    Goods goods= newGoods();

    goods.setName("java1");

    goods.setId("1");

    goodsMapper3.updateGoodsById(goods); // 第一步 更新操作

    sqlSession3.commit(); // 第二步 提交事务

    goodsMapper2.selectGoodsById("1");

    }public staticSqlSessionFactory getSqlSessionFactory() {

    String resource= "spring-ibatis.xml";if(sqlSessionFactory == null){try{

    sqlSessionFactory= newSqlSessionFactoryBuilder().build(Resources

    .getResourceAsReader(resource));

    }catch(IOException e) {//TODO Auto-generated catch block

    e.printStackTrace();

    }

    }returnsqlSessionFactory;

    }

    }

    看日志:

    ==> Preparing: select * from goods WHERE id = ?

    ==> Parameters: 1(String)<==Columns: id, name, price, detail, remark<== Row: 1, java1, 30.00, null, null

    <== Total: 1Opening JDBC Connection

    Created connection1998228836.==> Preparing: update goods set name = ? where id = ?

    ==> Parameters: java1(String), 1(String)<== Updates: 1Cache Hit Ratio [com.yht.mybatisTest.dao.GoodsDao]:0.0Opening JDBC Connection

    Created connection1945928717.==> Preparing: select * from goods WHERE id = ?

    ==> Parameters: 1(String)<==Columns: id, name, price, detail, remark<== Row: 1, java1, 30.00, null, null

    <== Total: 1

    总结:在更新操作,并提交事务后,清除了二级缓存,所以第二次查询时,是从数据库中查询的数据。接下来,就针对更新操作和提交事务这两个过程作分析。

    2.3.1 第一步 更新操作

    进入CachingExecutor类的update方法:

    public int update(MappedStatement ms, Object parameterObject) throwsSQLException {

    // 进入该方法,可知:清空了TransactionalCache中entriesToAddOnCommit和entriesToRemoveOnCommit的数据,同时clearOnCommit设置为true

    flushCacheIfRequired(ms);returndelegate.update(ms, parameterObject);

    但是二级缓存中的数据对象并未清除,所以进入第二步事务提交。

    2.3.2 第二步 事务提交

    最终进入TransactionalCache的commit方法:

    public voidcommit() {if(clearOnCommit) {

    // 由于在上一步更新操作中,clearOnCommit设置为了true,所以进入此方法:清除二级缓存中的数据

    delegate.clear();

    }else{for(RemoveEntry entry : entriesToRemoveOnCommit.values()) {

    entry.commit();

    }

    }for(AddEntry entry : entriesToAddOnCommit.values()) {

    entry.commit();

    }

    reset();

    }

    这就是清除二级缓存的过程。

    总结一下:其实主要就是把这几个类之间的关系及其作用搞清楚就行了:CachingExecutor,BaseExecutor,SimpleExecutor和TransactionalCache,PerpetualCache。这几个类也是整个请求过程中比较重要的类。

    展开全文
  • 二级缓存类创建流程 二级缓存的持有类是在sessionFactory创建的时候依然调用各种builder生成的 最终每个mapper.xml对应一个cache类放到configure类等待调用 重点看装饰器设置类: /** * 根据各种配置条件增加相应...
  • Mybatis 一级缓存和二级缓存

    千次阅读 2021-01-15 01:01:56
    MyBatis提供了一级缓存、二级缓存 这两个缓存机制,能够很好地处理和维护缓存,以提高系统的性能。本文的目的则是向读者详细介绍MyBatis的一级缓存,深入源码,解析MyBatis一级缓存的实现原理,并且针对一级缓存的...
  • # 一、前情提要 长久以来,对springboot项目中缓存的使用都会...对于第种观点,事实上现有的缓存结构也能够满足,只不过在加缓存的时候好加,可是在清理缓存的时候,我们需要手动对更新接口进行配置,可是由于项目的.
  • mybatis缓存 mybatis作为一个流行的持久化工具,缓存必然是缺少不了的组件。通过这篇文章,就让我们来了解一下mybatis的缓存。...第二种,就是非sqlSession级别的缓存了,我们通常称为二级缓存mybatis中的二级缓
  • 本文主要介绍在SpringBoot项目中如何使用Mybatis的一级、二级缓存,为了演示方便,本文的数据库采用H2内存数据库,数据库连接池默认使用SpringBoot2.X自带的hikariCP。正确的使用Mybatis缓存可以有效减少多余的数据库...
  • 前言: ...缓存范围为namespace级别,二级缓存mybatis默认会给我们开启的,是基于我们的会话来实现的,查询必须是在同一个会话下才会共享缓存区域。其实在我的理解为一级缓存也可以被认为是本地
  • Mybatis的一级缓存与二级缓存 缓存就是内存中的数据,常常来自对数据库查询结果的保存,使用缓存,我们可以避免频繁的与数据库 进行交互,进而提高响应速度。 Mybatis也提供了对缓存的支持,分为一级缓存和二级缓存...
  • 看过其他老师的帖子后自己整理一下,方便复习的时候用到,哪里有问题,还请各位老师务必指点我一下,我好...先测试一级缓存(可以理解为是基于SQLSession级别的) 1.找一个springboot项目 2.选定一个dao(Mapper)中
  • MyBatis提供了一级缓存、二级缓存 这两个缓存机制,能够很好地处理和维护缓存,以提高系统的性能。本文将介绍MyBatis的一级缓存,并深入源码解析MyBatis一级缓存的实现原理。 什么是一级缓存? 每当我们使用MyBatis...
  • 文章目录1、二级缓存1.1、cache使用1.2、原理2、Redis替代二级缓存2.1、获取ApplicationContext2.2、自定义cache实现类2.3、关联查询的缓存处理3、缓存优化策略3.1、对key进行优化 1、二级缓存 作缓存的对象类型...
  • 文章目录缓存介绍一级缓存一级缓存失效的原因二级缓存二级缓存使用步骤缓存相关属性缓存使用顺序二级缓存的使用原则缓存介绍MyBatis中使用缓存来提高其性能。当查询数据时, 会先从缓存中取出数据,如果缓存中没有,再...
  • MyBatis的缓存分为一级缓存和二级缓存(全局缓存),缓存示意图如下图所示。默认情况下,一级缓存是开启的,且不能被关闭。 MyBatis的一级缓存(SqlSession级别) 在同一个SqlSession中执行相同的SQL语句时,将查询...
  • Mybatis一级缓存和二级缓存的区别 缓存原理图: 一级缓存 Mybatis对缓存提供支持,但是在没有配置的默认情况下,它只开启一级缓存,一级缓存只是相对于同一个SqlSession而言。所以在参数和SQL完全一样的情况下,...
  • MyBatis 二级缓存

    2021-01-28 19:27:53
    MyBatis 二级缓存 一、二级缓存简介 二级缓存也叫全局缓存,由于一级缓存的作用域太低了,所以就诞生了二级缓存 它是基于mapper级别的缓存,一个***mapper.xml文件对应一个二级缓存 工作机制: 一个会话查询一条...
  • 上图描述了mybatis二级缓存工作原理:查询时如果存在就直接获取不存从库中获取 修改时直接清理暂存区,提交时提交的暂存区,此时我们看看源码如何实现的。 查询 @Override public <E> L
  • 1. Mybatis--二级缓存(namespace级别) 二级缓存也叫全局缓存,一级缓存作用域太低了,所以诞生了二级缓存 基于namespace级别的缓存,一个名称空间,对应一个二级缓存 工作机制 一个会话查询一条数据,这个数据...
  • Mybatis缓存(四)-二级缓存实现原理

    千次阅读 2021-09-07 19:50:22
    MyBatis二级缓存在默认情况下是关闭的,因此需要通过设置cacheEnabled参数值为true来开启二级缓存 SqlSession 将 执行Mapper的逻辑 委托给 Executor组件完成,而Executor接口有几种不同的实现,分别为SimpleExecutor...
  • 二级缓存原理Mybatis的二级缓存是指mapper映射文件。二级缓存是多个sqlSession共享的,其作用域是mapper下的同一个namespace。 在不同的sqlSession中,相同的namespace下,相同的查询sql语句并且参数也相同的情况...
  • 一、MyBatis级缓存1.MyBatis级缓存默认是开启的2.流程:3.MyBatis命中缓存原则1.StatmentId必须一致,否则无法命中2.传递给SQL的参数必须一致,比如,传入的map中有两个参数,只要传入的SQL中的id值是一样的,...
  • 文章目录Mybatis缓存为什么使用缓存一级缓存一级缓存的生命周期二级缓存二级缓存二级缓存详解配置二级缓存配置cache可以配置的属性如下:MyBatisUtils相关的动态sql生命周期和作用域SqlSessionFactoryBuilder...
  • 原标题:5 分钟,彻底掌握 MyBatis 缓存在计算机的世界中,缓存无处不在,操作系统有操作系统的缓存,数据库也会有数据库的缓存,各种中间件如Redis也是用来充当缓存的作用,编程语言中又可以利用内存来作为缓存。...
  • 如题,Spring整合MyBatis为什么会导致MyBatis的一级缓存失效? 一、搭建失效场景 测试用例为,查询一个String类型的字符串 基础的环境配置、扫描路径配置就不再重复,直接看测试数据相关的代码信息 1、对应的...
  • 在上一篇文章中我们主要对mybatis拦截器进行了研究。通过分析我们主要学习到mybatis这种插件的设计理念的优点。除此之外还有jdk动态代理与责任链模式的完美结合都是我们在项目实践中...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 23,082
精华内容 9,232
关键字:

mybatis二级缓存原理