栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Mybatis源码学习笔记之核心组件

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Mybatis源码学习笔记之核心组件

  官方对于Mybatis的介绍:

  MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
  官方文档:https://mybatis.org/mybatis-3/zh/index.html#

  Mybatis本质上帮我们省去JDBC一套的操作,和JDBC一样,操作数据库都需要建立连接、构建Statement、设置参数、执行SQL这几个步骤。

会话(SqlSession)

  核心作用是为用户提供API。API包括增、删、改、查以及提交、关闭等。下面是SqlSession的接口定义:

package org.apache.ibatis.session;

import java.io.Closeable;
import java.sql.Connection;
import java.util.List;
import java.util.Map;

import org.apache.ibatis.cursor.Cursor;
import org.apache.ibatis.executor.BatchResult;


public interface SqlSession extends Closeable {

  
   T selectOne(String statement);

  
   T selectOne(String statement, Object parameter);

  
   List selectList(String statement);

  
   List selectList(String statement, Object parameter);

  
   List selectList(String statement, Object parameter, RowBounds rowBounds);

  
   Map selectMap(String statement, String mapKey);

  
   Map selectMap(String statement, Object parameter, String mapKey);

  
   Map selectMap(String statement, Object parameter, String mapKey, RowBounds rowBounds);

  
   Cursor selectCursor(String statement);

  
   Cursor selectCursor(String statement, Object parameter);

  
   Cursor selectCursor(String statement, Object parameter, RowBounds rowBounds);

  
  void select(String statement, Object parameter, ResultHandler handler);

  
  void select(String statement, ResultHandler handler);

  
  void select(String statement, Object parameter, RowBounds rowBounds, ResultHandler handler);

  
  int insert(String statement);

  
  int insert(String statement, Object parameter);

  
  int update(String statement);

  
  int update(String statement, Object parameter);

  
  int delete(String statement);

  
  int delete(String statement, Object parameter);

  
  void commit();

  
  void commit(boolean force);

  
  void rollback();

  
  void rollback(boolean force);

  
  List flushStatements();

  
  @Override
  void close();

  
  void clearCache();

  
  Configuration getConfiguration();

  
   T getMapper(Class type);

  
  Connection getConnection();
}
执行器(Executor)

  核心功能包括:缓存维护、获取动态SQL、获取连接、以及最终的JDBC调用等。Mybatis源码最顶层有个Executor接口,有两个实现类, 分别是 baseExecutor、CachingExecutor。

baseExecutor

  主要是用于维护缓存和事务,它实现了Executor中的query与update方法。其中query方法中处理一级缓存逻辑,即根据SQL及参数判断缓存中是否存在数据,有就走缓存。否则就会调用子类的doQuery() 方法去查询数据库,然后在设置缓存。
   源码位置:org.apache.ibatis.executor.baseExecutor

  @Override
  public  List query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
    BoundSql boundSql = ms.getBoundSql(parameter);
    CacheKey key = createCacheKey(ms, parameter, rowBounds, boundSql);
    return query(ms, parameter, rowBounds, resultHandler, key, boundSql);
  }

  @SuppressWarnings("unchecked")
  @Override
  public  List 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 list;
    try {
      queryStack++;
      list = resultHandler == null ? (List) 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;
  }
  
 private  List queryFromDatabase(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
    List list;
    localCache.putObject(key, EXECUTION_PLACEHOLDER);
    try {
      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;
  }

   在update方法中有一个很重要的工作,就是清缓存

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

  对于这个接口MyBatis是有三个实现子类。分别是:SimpleExecutor、ReuseExecutor、BatchExecutor。

SimpleExecutor

​   SimpleExecutor是默认执行器,它的行为是每处理一次会话当中的SQl请求都会通过对应的StatementHandler 构建一个新个Statement。

ReuseExecutor

  和SimpleExecutor不同,ReuseExecutor在会话期间内的Statement进行缓存,并使用SQL语句作为Key。所以当执行下一请求的时候,不在重复构建Statement,而是从缓存中取出并设置参数,然后执行。

BatchExecutor

  BatchExecutor 顾名思义,它就是用来作批处理的。但会将所有SQL请求集中起来,最后调用Executor.flushStatements() 方法时一次性将所有请求发送至数据库。
  只有连续相同的SQL语句并且相同的SQL映射声明,才会重用Statement,并利用其批处理功能。否则会构建一个新的Satement然后在flushStatements() 时一次执行。

CachingExecutor

  处理二级缓存,单独抽出来处理。CachingExecutor 对原有的执行器进行包装,处理完二级缓存逻辑之后,把SQL执行相关的逻辑交给实际的Executor处理。
  关于Mybatis一级缓存、二级缓存的内容将在下篇介绍:Mybatis源码学习笔记之Mybatis一级缓存。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/351178.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号