前面几篇博客我们介绍了Excutor及抽象类BaseExecutor和实现类SimpleExecutor、BatchExecutor和ReuseExecutor:

博客列表:

Mybatis执行Executor(一)

Mybatis执行BaseExecutor(二)

Mybatis执行SimpleExecutor(三)

Mybatis执行BatchExecutor(四)

Mybatis执行ReuseExecutor(五)

接下来我们再介绍一个比较重要的类CachingExecutor,通过类名我们可以猜测到,这个Executor执行类是使用内存的,将数据保存到缓存中,这样可以有效的解决增删改查性能。缓存的作用域为mapper(namespace),所以同一个namespace的操作会影响到相同作用域下的缓存,这样不同的域对同一个表进行操作很有可能导致缓存中的数据不一样,出现问题,还是不推荐使用。

public class CachingExecutor implements Executor {

  private Executor delegate;
  private TransactionalCacheManager tcm = new TransactionalCacheManager();

  public CachingExecutor(Executor delegate) {
    this.delegate = delegate;
    delegate.setExecutorWrapper(this);
  }

  public Transaction getTransaction() {
    return delegate.getTransaction();
  }

  public void close(boolean forceRollback) {
    try {
      //issues #499, #524 and #573
      if (forceRollback) {
        tcm.rollback();
      } else {
        tcm.commit();
      }
    } finally {
      delegate.close(forceRollback);
    }
  }
  //是否关闭了executor
  public boolean isClosed() {
    return delegate.isClosed();
  }

  public int update(MappedStatement ms, Object parameterObject) throws SQLException {
	//是否需要更缓存
    flushCacheIfRequired(ms);
	//更新数据
    return delegate.update(ms, parameterObject);
  }

  public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
    BoundSql boundSql = ms.getBoundSql(parameterObject);
	//创建缓存值
    CacheKey key = createCacheKey(ms, parameterObject, rowBounds, boundSql);
	//获取记录
    return query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
  }

  public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql)
      throws SQLException {
    //获取缓存
    Cache cache = ms.getCache();
	//如果设置保存到缓存
    if (cache != null) {
      flushCacheIfRequired(ms);
      if (ms.isUseCache() && resultHandler == null) {
        ensureNoOutParams(ms, parameterObject, boundSql);
        @SuppressWarnings("unchecked")
		//从缓存中获取数据
        List<E> list = (List<E>) tcm.getObject(cache, key);
		//为空执行一次,将结果保存到缓存中
        if (list == null) {
          list = delegate.<E> query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
          tcm.putObject(cache, key, list); // issue #578. Query must be not synchronized to prevent deadlocks
        }
        return list;
      }
    }
    return delegate.<E> query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
  }

  public List<BatchResult> flushStatements() throws SQLException {
    return delegate.flushStatements();
  }

  public void commit(boolean required) throws SQLException {
    delegate.commit(required);
    tcm.commit();
  }

  public void rollback(boolean required) throws SQLException {
    try {
      delegate.rollback(required);
    } finally {
      if (required) {
        tcm.rollback();
      }
    }
  }

  private void ensureNoOutParams(MappedStatement ms, Object parameter, BoundSql boundSql) {
    if (ms.getStatementType() == StatementType.CALLABLE) {
      for (ParameterMapping parameterMapping : boundSql.getParameterMappings()) {
        if (parameterMapping.getMode() != ParameterMode.IN) {
          throw new ExecutorException("Caching stored procedures with OUT params is not supported.  Please configure useCache=false in " + ms.getId() + " statement.");
        }
      }
    }
  }

  public CacheKey createCacheKey(MappedStatement ms, Object parameterObject, RowBounds rowBounds, BoundSql boundSql) {
    return delegate.createCacheKey(ms, parameterObject, rowBounds, boundSql);
  }

  public boolean isCached(MappedStatement ms, CacheKey key) {
    return delegate.isCached(ms, key);
  }

  public void deferLoad(MappedStatement ms, MetaObject resultObject, String property, CacheKey key, Class<?> targetType) {
    delegate.deferLoad(ms, resultObject, property, key, targetType);
  }

  public void clearLocalCache() {
    delegate.clearLocalCache();
  }

  private void flushCacheIfRequired(MappedStatement ms) {
    Cache cache = ms.getCache();
    if (cache != null && ms.isFlushCacheRequired()) {
      tcm.clear(cache);
    }
  }

  @Override
  public void setExecutorWrapper(Executor executor) {
    throw new UnsupportedOperationException("This method should not be called");
  }

}

Mybatis执行CachingExecutor(六)的更多相关文章

  1. Springboot中mybatis执行逻辑源码分析

    Springboot中mybatis执行逻辑源码分析 在上一篇springboot整合mybatis源码分析已经讲了我们的Mapper接口,userMapper是通过MapperProxy实现的一个动 ...

  2. mybatis执行批量更新update

    Mybatis的批量插入这里有http://ljhzzyx.blog.163.com/blog/static/38380312201353536375/.目前想批量更新,如果update的值是相同的话 ...

  3. 一图看懂mybatis执行过程

    一图看懂mybatis执行过程,不再懵B了

  4. 【mybatis】mybatis执行一个update方法,返回值为1,但是数据库中数据并未更新,粘贴sql语句直接在数据库执行,等待好久报错:Lock wait timeout exceeded; try restarting transaction

    今天使用mybatis和jpa的过程中,发现这样一个问题: mybatis执行一个update方法,返回值为1,但是数据库中数据并未更新,粘贴sql语句直接在数据库执行,等待好久报错:Lock wai ...

  5. mybatis执行多条sql语句

    1,mybatis执行多条sql语句,有以下几种思路, a,存储过程 b,修改jdbc的参数,允许执行多条语句,如下所示: sqlserver可以直接使用begin,end来执行多条语句, mysql ...

  6. mybatis执行过程及经典面试题

    Mybatis执行流程 mybatis中xml解析是通过SqlSessionFactoryBuilder.build()方法. 初始化mybatis(解析xml文件构建成Configuration对象 ...

  7. mybatis 逆向工程(通过数据库表针对单表自动生成mybatis执行所需要的代码)

    mybatis需要程序员自己编写sql语句,mybatis官方提供逆向工程,可以针对单表自动生成mybatis执行所需要的代码(mapper.java.mapper.xml.pojo…),可以让程序员 ...

  8. mybatis 执行流程以及初用错误总结

    mappper 配置文件  头文件: 1.   <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" &q ...

  9. MyBatis执行流程的各阶段介绍

    目录 一.mybatis极简示例 1.1 创建mybatis配置文件 1.2 创建数据库表 1.3 创建javabean 1.4 创建mapper映射文件 1.5 运行测试 二.mybatis的几大“ ...

随机推荐

  1. Linux学习之CentOS(十六)-----内存置换空间(swap)之建置(转)

    内存置换空间(swap)之建置 安装时一定需要的两个 partition 啰! 一个是根目录,另外一个就是 swap(内存置换空间), swap 的功能就是在应付物理内存不足的情况下所造成的内存延伸记 ...

  2. Oracle中表字段相关操作举例

    --创建测试表 create or replace table student ( xh ), --学号 xm ), --姓名 sex ), --性别 birthday date, --日期 sal ...

  3. CSharpGL(48)用ShadowVolume画模型的影子

    CSharpGL(48)用ShadowVolume画模型的影子 在Per-Fragment Operations & Tests阶段,有一个步骤是模版测试(Stencil Test).依靠这一 ...

  4. 《Java多线程编程核心技术》推荐

    写这篇博客主要是给猿友们推荐一本书<Java多线程编程核心技术>. 之所以要推荐它,主要因为这本书写得十分通俗易懂,以实例贯穿整本书,使得原本抽象的概念,理解起来不再抽象. 只要你有一点点 ...

  5. 集群技术(二) MySQL集群简介与配置详解

    when?why? 用MySQL集群? 减少数据中心结点压力和大数据量处理(读写分离),采用把MySQL分布,一个或多个application对应一个MySQL数据库.把几个MySQL数据库公用的数据 ...

  6. XML Condition And

    <Target Name="CustomBuildStep" Condition="'@(CustomBuildStep)' != '' and '$(Select ...

  7. Django项目实践4 - Django站点管理(后台管理员)

    http://blog.csdn.net/pipisorry/article/details/45079751 上篇:Django项目实践3 - Django模型 Introduction 对于某一类 ...

  8. Servlet - 基础

    Servlet 标签 : Java与Web HTTP协议 HTTP(hypertext transport protocol),即超文本传输协议.这个协议详细规定了浏览器(Browser)和万维网服务 ...

  9. SQLite Update 语句(http://www.w3cschool.cc/sqlite/sqlite-update.html)

    SQLite Update 语句 SQLite 的 UPDATE 查询用于修改表中已有的记录.可以使用带有 WHERE 子句的 UPDATE 查询来更新选定行,否则所有的行都会被更新. 语法 带有 W ...

  10. ListView嵌套GridView

    首先,我们通过两个实例来了解下本篇文章所讲的重点,看下图: 微博: 陌陌: 大家应该对这两款软件并不陌生,接下来,我将列举下本文将要实现的几个点: 1.ListView嵌套GridView,互不冲突, ...