mybatis源码学习

一、整体架构

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
SqlSession是接口,里面各种增删改查接口,Executor里面是具体的实现

SimpleExecutor
 @Test
    public void test1() throws SQLException {
        SimpleExecutor executor = new SimpleExecutor(configuration, jdbcTransaction);
        //mapper中对应的方法
        MappedStatement ms = configuration.getMappedStatement("com.alipay.mybatis.persion.mapper.PersonMapper.findALl");
        List<Person> es = executor.doQuery(ms, 2, RowBounds.DEFAULT,SimpleExecutor.NO_RESULT_HANDLER, ms.getBoundSql(2));
        executor.doQuery(ms, 2, RowBounds.DEFAULT,SimpleExecutor.NO_RESULT_HANDLER, ms.getBoundSql(2));
        System.out.println(es.get(1));
    }

在这里插入图片描述
可见进行了两次预处理

ReuseExecutor
@Test
    public void test2() throws SQLException {
        ReuseExecutor executor = new ReuseExecutor(configuration, jdbcTransaction);
        //mapper中对应的方法
        MappedStatement ms = configuration.getMappedStatement("com.alipay.mybatis.persion.mapper.PersonMapper.findALl");
        List<Person> es = executor.doQuery(ms, 2, RowBounds.DEFAULT,SimpleExecutor.NO_RESULT_HANDLER, ms.getBoundSql(2));
        executor.doQuery(ms, 2, RowBounds.DEFAULT,SimpleExecutor.NO_RESULT_HANDLER, ms.getBoundSql(2));
        System.out.println(es.get(1));
    }

在这里插入图片描述
只进行了一次预处理

BatchExexutor

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
对于修改操作进行批处理,只编译一次
在这里插入图片描述
BaseExecutor中定义了下面三个执行器中的一些公共方法,如获取连接,缓存
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

 @Test
    public void test3() throws SQLException {
        Executor executor = new SimpleExecutor(configuration, jdbcTransaction);
        //mapper中对应的方法
        MappedStatement ms = configuration.getMappedStatement("com.alipay.mybatis.persion.mapper.PersonMapper.findALl");
        executor.query(ms, 2, RowBounds.DEFAULT,Executor.NO_RESULT_HANDLER);
        executor.query(ms, 2, RowBounds.DEFAULT,SimpleExecutor.NO_RESULT_HANDLER);

    }

在这里插入图片描述
可见只进行了一次编译,是因为query中有缓存的操作

BaseExecutor的query方法
@Override
  public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
    BoundSql boundSql = ms.getBoundSql(parameter);//获取动态sql
    CacheKey key = createCacheKey(ms, parameter, rowBounds, boundSql);//获取缓存的key
    return query(ms, parameter, rowBounds, resultHandler, key, boundSql);//调用重载
  }

//重载的query
@Override
  public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
    ErrorContext.instance().resource(ms.getResource()).activity("executing a query").object(ms.getId());
    if (closed) {
      throw new ExecutorException("Executor was closed.");
    }
    if (queryStack == 0 && ms.isFlushCacheRequired()) {
      clearLocalCache();
    }
    List<E> list;
    try {
      queryStack++;
      list = resultHandler == null ? (List<E>) localCache.getObject(key) : null;//获取本地一级缓存
      if (list != null) {
      //如果有缓存
        handleLocallyCachedOutputParameters(ms, key, parameter, boundSql);
      } else {
      //如果没有缓存
        list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);
      }
    } finally {
      queryStack--;
    }
    if (queryStack == 0) {
      for (DeferredLoad deferredLoad : deferredLoads) {
        deferredLoad.load();
      }
      // issue #601
      deferredLoads.clear();
      if (configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) {
        // issue #482
        clearLocalCache();
      }
    }
    return list;
  }

//BaseExecutor

private <E> List<E> queryFromDatabase(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
    List<E> list;
    localCache.putObject(key, EXECUTION_PLACEHOLDER);
    try {
    //走到了doQuery方法
      list = doQuery(ms, parameter, rowBounds, resultHandler, boundSql);
    } finally {
      localCache.removeObject(key);
    }
    localCache.putObject(key, list);
    if (ms.getStatementType() == StatementType.CALLABLE) {
      localOutputParameterCache.putObject(key, parameter);
    }
    return list;
  }


//SimpleExecutor
@Override
  public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
    Statement stmt = null;
    try {
      Configuration configuration = ms.getConfiguration();
      StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
      stmt = prepareStatement(handler, ms.getStatementLog());
      return handler.query(stmt, resultHandler);
    } finally {
      closeStatement(stmt);
    }
  }

二级缓存

在这里插入图片描述
二级缓存的实现在CachingExecutor里面实现,采用装饰着模式

二级缓存需要自己来配,属于外部缓存

 @Test
    public void test4() throws SQLException {
        Executor executor = new SimpleExecutor(configuration, jdbcTransaction);
        //走二级缓存
        CachingExecutor cachingExecutor = new CachingExecutor(executor);
        //mapper中对应的方法

        cachingExecutor.query(ms, 2, RowBounds.DEFAULT,Executor.NO_RESULT_HANDLER);
        cachingExecutor.commit(true);//先走二级缓存再走一级缓存,由于我没有配二级缓存所以不会生效
        cachingExecutor.query(ms, 2, RowBounds.DEFAULT,Executor.NO_RESULT_HANDLER);
    }

@Override
  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);
  }

  @Override
  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, boundSql);
        @SuppressWarnings("unchecked")
        //获取缓存的内容
        List<E> list = (List<E>) tcm.getObject(cache, key);
        //如果缓存的内容为空
        if (list == null) {
        //交给下一个执行器,就是BaseExecutor
          list = delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
          tcm.putObject(cache, key, list); // issue #578 and #116
        }
        return list;
      }
    }
    //没有就走一级缓存,一级缓存定义在BaseExecutor   就是BaseExecutor
    return delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
  }

在这里插入图片描述
在这里插入图片描述

小总结

SqlSession中的方法会间接调用executor的query方法,在CachingExecutor中的query实现了该方法,里面有二级缓存的逻辑,然后里面的delegate指向下一个执行器BaseExecutor,里面有一级缓存和获取连接等操作,调用query方法,query方法里面又有doQuery方法,这个doQuery方法由下面三个类中的一个来实现

通过sqlsession来调用

在这里插入图片描述

在这里插入图片描述

清空缓存的操作

**加粗样式
**
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
一级缓存失效的情况,是你用spring没有用到事务,只要把查询都写到一个事务里面,缓存就会生效,一个事务对应一个连接,一个连接就对应一次会话
在这里插入图片描述

spring是如何调用mybatis的工厂的

在这里插入图片描述

mybatis缓存体系

在这里插入图片描述
在这里插入图片描述
会话不是线程安全的,所以一级缓存也不是线程安全的,所以无法跨线程使用
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
commit应该加在后面
在这里插入图片描述

StatementHandler

在这里插入图片描述
一个SqlSession对应一个Executor对应多个个StatementHandler

StatementHandler的定义

在这里插入图片描述
在这里插入图片描述

结果集映射在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

ResultSetHandler->DefaultResultSetHandler

Mybatis映射体系

结果集和Java对象的一个互相的映射

MeataObject结果集映射工具类

在这里插入图片描述
我们可以采用工具类就可以直接把object转化为Blog类
在这里插入图片描述
在这里插入图片描述
Author是一个类,可以给里面的属性name赋值
在这里插入图片描述
在这里插入图片描述

MetaObject源码解析

结果集映射ResultMap

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

动态sql

在这里插入图片描述
在这里插入图片描述

SqlSource解析流程

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

SqlNode语法树结构

在这里插入图片描述

Configuration配置体系

在这里插入图片描述

Configuration核心功能

在这里插入图片描述
在这里插入图片描述

Configuration组件的构建过程

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

MappedStatement的解析

它是解析sql的所以比较核心
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

插件的四大组件

在这里插入图片描述
在这里插入图片描述

分页插件编码

在这里插入图片描述
在这里插入图片描述
就是在预处理的时候对它进行一个拦截
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值