在月黑风高的某天夜晚,boss chen语重心长的发条了消息给小草说:“小草啊,是时候写写博客来记录平常自己积累的东西了......”。小草一听,平常没有写博客的习惯,在平常开发中只是用笔记记录自己的所得(分散的小点),写博客的心思还处于萌芽之中,boss chen的话彻底让萌芽“破土而出”。

  之后便有了本博主的博客之旅......小草的Dream。

SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。

  第一次写博客,也不知道从哪里开始写,想来想去先从平常接触比较多的mybatis开始写吧!

mybatis的缓存机制

一级缓存

mybatis配置中是默认启用一级缓存的(默认的是SESSION级别),当然也可以再次手动设置

<setting name="localCacheScope" value="SESSION"/>

 注:一级缓存有连个选项,SESSION或者STATEMENT,默认是SESSION。

mybati缓存机制之一级缓存 随笔 第1张

测试案例:

  1.在一个service中对某个id查询多次

mybati缓存机制之一级缓存 随笔 第2张

  可以看出真正与数据库交互的只有第一次查询,第二次,第三次查询是通过查询缓存得出的。

 mybati缓存机制之一级缓存 随笔 第3张

  2.当在同一个会话中进行了增删语句之后,一级缓存会失效

     例如当在上述例子中的第二部修改为删除的一条语句,一级缓存会失效

  mybati缓存机制之一级缓存 随笔 第4张

    可以看出在第二部进行删除操作后,1~3步骤都对数据库进行操作,所以在进行增删的操作后,执行相同的查询语句,一级缓存会失效。

  mybati缓存机制之一级缓存 随笔 第5张

  3.原理见图(欢迎指正)

 mybati缓存机制之一级缓存 随笔 第6张

  4.SqlSession 方法解析:

    SqlSession中提供了与数据交互的方法

  <T> T selectOne(String var1);

  <T> T selectOne(String var1, Object var2);

  <E> List<E> selectList(String var1);

  <E> List<E> selectList(String var1, Object var2);

  <E> List<E> selectList(String var1, Object var2, RowBounds var3);

  <K, V> Map<K, V> selectMap(String var1, String var2);

  <K, V> Map<K, V> selectMap(String var1, Object var2, String var3);

  <K, V> Map<K, V> selectMap(String var1, Object var2, String var3, RowBounds var4);

  <T> Cursor<T> selectCursor(String var1);

  <T> Cursor<T> selectCursor(String var1, Object var2);

  <T> Cursor<T> selectCursor(String var1, Object var2, RowBounds var3);

  void select(String var1, Object var2, ResultHandler var3);

  void select(String var1, ResultHandler var2);

  void select(String var1, Object var2, RowBounds var3, ResultHandler var4);

  int insert(String var1);

  int insert(String var1, Object var2);

  int update(String var1);

  int update(String var1, Object var2);

  int delete(String var1);

  int delete(String var1, Object var2);

  void commit();

  void commit(boolean var1);

  void rollback();

  void rollback(boolean var1);

  List<BatchResult> flushStatements();

  void close();

  void clearCache();

  Configuration getConfiguration();

  <T> T getMapper(Class<T> var1);

  Connection getConnection();

  Executor是与操作数据库有关的职责都会被委托。Executor有若干个实现类,为Executor赋予了不同的能力,之后参考源码进行深入学习。

mybati缓存机制之一级缓存 随笔 第7张

  5.至此,通过源码的分析一个简单的上述案例的原因(insert/delete/update方法,缓存就会刷新的原因)

    SqlSession的insert方法和delete方法,都会统一走update的流程,代码如下所示:

  @Override

  public int insert(String statement, Object parameter) { return update(statement, parameter);
  }

   @Override
  public int delete(String statement) { return update(statement, null);
  }

  update方法也是委托给了Executor执行。BaseExecutor的执行方法如下所示。

  @Override

  public int update(MappedStatement ms, Object parameter) throws SQLException {
    ErrorContext.instance().resource(ms.getResource()).activity("executing an update").object(ms.getId());

     if (closed) {

       throw new ExecutorException("Executor was closed.");
    }
      clearLocalCache();

        return doUpdate(ms, parameter);
  }

  每次执行update前都会清空localCache。

mybatis一级缓存:

MyBatis一级缓存的生命周期和SqlSession一致。

MyBatis一级缓存内部设计简单,只是一个没有容量限定的HashMap,在缓存的功能性上有所欠缺。

MyBatis的一级缓存最大范围是SqlSession内部,有多个SqlSession或者分布式的环境下,数据库写操作会引起脏数据,建议设定缓存级别为Statement。

 

(未完待续......)

  之后一遍介绍mybatis的二级缓存,请期待......

 

 

   

 

扫码关注我们
微信号:SRE实战
拒绝背锅 运筹帷幄