1.MyBatis源码解读——项目层次结构

MyBatis主要包含的核心部件

  • SqlSession : Mybatis工作的主要顶层API,表示和数据库交互的会话,完成必要数据库增删改查功能。这是MyBatis主要的一个类,用来执行SQL,获取映射器,管理事务。通常情况下,在程序中使用的Mybatis的API就是这个接口定义的方法。
  • Executor: Mybatis执行器,是Mybatis调度的核心,负责SQL语句的生成和查询缓存的维护
  • StatementHandler: 封装了JDBC Statement操作,负责对JDBC statement的操作,如设置参数、将Statement结果集转换成List集合。
  • ParameterHandler :参数处理器,负责对用户传递的参数转换成JDBC Statement所需要的参数
  • ResultSetHandler :结果集处理器,负责将JDBC返回的ResultSet结果集对象转换成List类型的集合
  • TypeHandler: 类型处理器,负责java数据类型和jdbc数据类型之间的映射和转换
  • MappedStatement :映射语句,维护了一条<select|update|delete|insert>节点的封装
  • SqlSource: SQL源码,负责根据用户传递的parameterObject,动态地生成SQL语句,将信息封装到BoundSql对象中,并返回
  • BoundSql:绑定的SQL,是从SqlSource而来,将动态内容都处理完得到的SQL语句字符串,其中包括?,还有绑定的参数
  • Configuration:Mybatis所有的配置信息都维护在Configuration对象之中
  • MapperProxyFactory:映射器代理工厂,主要是使用jdk代理mapper的实现以实现调用SqlSessoin,接口类名称对应配置文件的namespace的值,等标签的id对应方法名称。

关系图如下(图片来源于网络)
1.MyBatis源码解读——项目层次结构

SqlSession源码

package org.apache.ibatis.session;


/**
 * 这是MyBatis主要的一个类,用来执行SQL,获取映射器,管理事务,是顶层API接口
 *
 * 通常情况下,我们在应用程序中使用的Mybatis的API就是这个接口定义的方法。
 *
 */
public interface SqlSession extends Closeable {
  /**
   * Retrieve a single row mapped from the statement key
   * 根据指定的SqlID获取一条记录的封装对象
   * @param <T> the returned object type 封装之后的对象类型
   * @param statement sqlID
   * @return Mapped object 封装之后的对象
   */
  <T> T selectOne(String statement);
  /**
   * Retrieve a single row mapped from the statement key and parameter.
   * 根据指定的SqlID获取一条记录的封装对象,只不过这个方法容许我们可以给sql传递一些参数
   * 一般在实际使用中,这个参数传递的是pojo,或者Map或者ImmutableMap
   * @param <T> the returned object type
   * @param statement Unique identifier matching the statement to use.
   * @param parameter A parameter object to pass to the statement.
   * @return Mapped object
   */
  <T> T selectOne(String statement, Object parameter);
  /**
   * Retrieve a list of mapped objects from the statement key and parameter.
   * 根据指定的sqlId获取多条记录
   * @param <E> the returned list element type
   * @param statement Unique identifier matching the statement to use.
   * @return List of mapped object
   */
  <E> List<E> selectList(String statement);  
  /**
   * Retrieve a list of mapped objects from the statement key and parameter.
   * 获取多条记录,这个方法容许我们可以传递一些参数
   * @param <E> the returned list element type
   * @param statement Unique identifier matching the statement to use.
   * @param parameter A parameter object to pass to the statement.
   * @return List of mapped object
   */
  <E> List<E> selectList(String statement, Object parameter);  
  /**
   * Retrieve a list of mapped objects from the statement key and parameter,
   * within the specified row bounds.
   * 获取多条记录,这个方法容许我们可以传递一些参数,不过这个方法容许我们进行
   * 分页查询。
   *
   * 需要注意的是默认情况下,Mybatis为了扩展性,仅仅支持内存分页。也就是会先把
   * 所有的数据查询出来以后,然后在内存中进行分页。因此在实际的情况中,需要注意
   * 这一点。
   *
   * 一般情况下公司都会编写自己的Mybatis 物理分页插件
   * @param <E> the returned list element type
   * @param statement Unique identifier matching the statement to use.
   * @param parameter A parameter object to pass to the statement.
   * @param rowBounds  Bounds to limit object retrieval
   * @return List of mapped object
   */
  <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds);  
  /**
   * The selectMap is a special case in that it is designed to convert a list
   * of results into a Map based on one of the properties in the resulting
   * objects.
   * Eg. Return a of Map[Integer,Author] for selectMap("selectAuthors","id")
   * 将查询到的结果列表转换为Map类型。
   * @param <K> the returned Map keys type
   * @param <V> the returned Map values type
   * @param statement Unique identifier matching the statement to use.
   * @param mapKey The property to use as key for each value in the list. 这个参数会作为结果map的key
   * @return Map containing key pair data.
   */
  <K, V> Map<K, V> selectMap(String statement, String mapKey);  
  /**
   * The selectMap is a special case in that it is designed to convert a list
   * of results into a Map based on one of the properties in the resulting
   * objects.
   * 将查询到的结果列表转换为Map类型。这个方法容许我们传入需要的参数
   * @param <K> the returned Map keys type
   * @param <V> the returned Map values type
   * @param statement Unique identifier matching the statement to use.
   * @param parameter A parameter object to pass to the statement.
   * @param mapKey The property to use as key for each value in the list.
   * @return Map containing key pair data.
   */
  <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey);
  /**
   * The selectMap is a special case in that it is designed to convert a list
   * of results into a Map based on one of the properties in the resulting
   * objects.
   * 获取多条记录,加上分页,并存入Map
   * @param <K> the returned Map keys type
   * @param <V> the returned Map values type
   * @param statement Unique identifier matching the statement to use.
   * @param parameter A parameter object to pass to the statement.
   * @param mapKey The property to use as key for each value in the list.
   * @param rowBounds  Bounds to limit object retrieval
   * @return Map containing key pair data.
   */
  <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey, RowBounds rowBounds);  
  /**
   * Retrieve a single row mapped from the statement key and parameter
   * using a {@code ResultHandler}.
   *
   * @param statement Unique identifier matching the statement to use.
   * @param parameter A parameter object to pass to the statement.
   * @param handler ResultHandler that will handle each retrieved row
   * @return Mapped object
   */
  void select(String statement, Object parameter, ResultHandler handler);
  /**
   * Retrieve a single row mapped from the statement
   * using a {@code ResultHandler}.
   * 获取一条记录,并转交给ResultHandler处理。这个方法容许我们自己定义对
   * 查询到的行的处理方式。不过一般用的并不是很多
   * @param statement Unique identifier matching the statement to use.
   * @param handler ResultHandler that will handle each retrieved row
   * @return Mapped object
   */
  void select(String statement, ResultHandler handler);  
  /**
   * Retrieve a single row mapped from the statement key and parameter
   * using a {@code ResultHandler} and {@code RowBounds}
   * 获取一条记录,加上分页,并转交给ResultHandler处理
   * @param statement Unique identifier matching the statement to use.
   * @param rowBounds RowBound instance to limit the query results
   * @param handler ResultHandler that will handle each retrieved row
   * @return Mapped object
   */
  void select(String statement, Object parameter, RowBounds rowBounds, ResultHandler handler);  


  /**
   * Execute an insert statement.
   * 插入记录。一般情况下这个语句在实际项目中用的并不是太多,而且更多使用带参数的insert函数
   * @param statement Unique identifier matching the statement to execute.
   * @return int The number of rows affected by the insert.
   */
  int insert(String statement);
  /**
   * Execute an insert statement with the given parameter object. Any generated
   * autoincrement values or selectKey entries will modify the given parameter
   * object properties. Only the number of rows affected will be returned.
   * 插入记录,容许传入参数。
   * @param statement Unique identifier matching the statement to execute.
   * @param parameter A parameter object to pass to the statement.
   * @return int The number of rows affected by the insert. 注意返回的是受影响的行数
   */
  int insert(String statement, Object parameter);
  /**
   * Execute an update statement. The number of rows affected will be returned.
   * 更新记录。返回的是受影响的行数
   * @param statement Unique identifier matching the statement to execute.
   * @return int The number of rows affected by the update.
   */
  int update(String statement);
  /**
   * Execute an update statement. The number of rows affected will be returned.
   * 更新记录
   * @param statement Unique identifier matching the statement to execute.
   * @param parameter A parameter object to pass to the statement.
   * @return int The number of rows affected by the update. 返回的是受影响的行数
   */
  int update(String statement, Object parameter);
  /**
   * Execute a delete statement. The number of rows affected will be returned.
   * 删除记录
   * @param statement Unique identifier matching the statement to execute.
   * @return int The number of rows affected by the delete. 返回的是受影响的行数
   */
  int delete(String statement);
  /**
   * Execute a delete statement. The number of rows affected will be returned.
   * 删除记录
   * @param statement Unique identifier matching the statement to execute.
   * @param parameter A parameter object to pass to the statement.
   * @return int The number of rows affected by the delete. 返回的是受影响的行数
   */
  int delete(String statement, Object parameter);

  //以下是事务控制方法,commit,rollback
  /**
   * Flushes batch statements and commits database connection.
   * Note that database connection will not be committed if no updates/deletes/inserts were called.
   * To force the commit call {@link SqlSession#commit(boolean)}
   */
  void commit();
  /**
   * Flushes batch statements and commits database connection.
   * @param force forces connection commit
   */
  void commit(boolean force);

  /**
   * Discards pending batch statements and rolls database connection back.
   * Note that database connection will not be rolled back if no updates/deletes/inserts were called.
   * To force the rollback call {@link SqlSession#rollback(boolean)}
   */
  void rollback();

  /**
   * Discards pending batch statements and rolls database connection back.
   * Note that database connection will not be rolled back if no updates/deletes/inserts were called.
   * @param force forces connection rollback
   */
  void rollback(boolean force);
  /**
   * Flushes batch statements.
   * 刷新批处理语句,返回批处理结果
   * @return BatchResult list of updated records
   * @since 3.0.6
   */
  List<BatchResult> flushStatements();

  /**
   * Closes the session
   * 关闭Session
   */
  @Override
  void close();

  /**
   * Clears local session cache
   * 清理Session缓存
   */
  void clearCache();

  /**
   * Retrieves current configuration
   * 得到配置
   * @return Configuration
   */
  Configuration getConfiguration();

  /**
   * Retrieves a mapper.
   * 得到映射器
   * 这个巧妙的使用了泛型,使得类型安全
   * 到了MyBatis 3,还可以用注解,这样xml都不用写了
   * @param <T> the mapper type
   * @param type Mapper interface class
   * @return a mapper bound to this SqlSession
   */
  <T> T getMapper(Class<T> type);

  /**
   * Retrieves inner database connection
   * 得到数据库连接
   * @return Connection
   */
  Connection getConnection();
}

Executor 执行器 源码

package org.apache.ibatis.executor;
public interface Executor {

  //不需要ResultHandler
  ResultHandler NO_RESULT_HANDLER = null;

  //更新
  int update(MappedStatement ms, Object parameter) throws SQLException;

  //查询,带分页,带缓存,BoundSql
  <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey cacheKey, BoundSql boundSql) throws SQLException;

  //查询,带分页
  <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException;

  //刷新批处理语句
  List<BatchResult> flushStatements() throws SQLException;

  //提交和回滚,参数是是否要强制
  void commit(boolean required) throws SQLException;

  void rollback(boolean required) throws SQLException;

  //创建CacheKey
  CacheKey createCacheKey(MappedStatement ms, Object parameterObject, RowBounds rowBounds, BoundSql boundSql);

  //判断是否缓存了
  boolean isCached(MappedStatement ms, CacheKey key);

  //清理Session缓存
  void clearLocalCache();

  //延迟加载
  void deferLoad(MappedStatement ms, MetaObject resultObject, String property, CacheKey key, Class<?> targetType);

  Transaction getTransaction();

  void close(boolean forceRollback);

  boolean isClosed();

  void setExecutorWrapper(Executor executor);

}

StatementHandler 语句处理器

package org.apache.ibatis.executor.statement;
public interface StatementHandler {

  //准备语句
  Statement prepare(Connection connection)
      throws SQLException;

  //参数化
  void parameterize(Statement statement)
      throws SQLException;

  //批处理
  void batch(Statement statement)
      throws SQLException;

  //update
  int update(Statement statement)
      throws SQLException;

  //select-->结果给ResultHandler
  <E> List<E> query(Statement statement, ResultHandler resultHandler)
      throws SQLException;

  //得到绑定sql
  BoundSql getBoundSql();

  //得到参数处理器
  ParameterHandler getParameterHandler();

}

ParameterHandler 参数处理器

public interface ParameterHandler {

  //得到参数
  Object getParameterObject();

  //设置参数
  void setParameters(PreparedStatement ps)
      throws SQLException;

}

ResultSetHandler 结果集处理器

public interface ResultSetHandler {

  //处理结果集
  <E> List<E> handleResultSets(Statement stmt) throws SQLException;

  //处理OUT参数
  void handleOutputParameters(CallableStatement cs) throws SQLException;

}

TypeHandler类型处理器

public interface TypeHandler<T> {

  //设置参数
  void setParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException;

  //取得结果,供普通select用
  T getResult(ResultSet rs, String columnName) throws SQLException;

  //取得结果,供普通select用
  T getResult(ResultSet rs, int columnIndex) throws SQLException;

  //取得结果,供SP用
  T getResult(CallableStatement cs, int columnIndex) throws SQLException;

}

MappedStatement 映射的语句

public final class MappedStatement {
	//...
	//SQL源码
  private SqlSource sqlSource;
  private Cache cache;
  private ParameterMap parameterMap;
  private List<ResultMap> resultMaps;
  private boolean flushCacheRequired;
  private boolean useCache;
  private boolean resultOrdered;
  private SqlCommandType sqlCommandType;
  private KeyGenerator keyGenerator;
  private String[] keyProperties;
  private String[] keyColumns;
  private boolean hasNestedResultMaps;
  private String databaseId;
  private Log statementLog;
  private LanguageDriver lang;
  private String[] resultSets;

//...
public BoundSql getBoundSql(Object parameterObject) {
	//其实就是调用sqlSource.getBoundSql
    BoundSql boundSql = sqlSource.getBoundSql(parameterObject);
    //剩下的可以暂时忽略
    List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
    if (parameterMappings == null || parameterMappings.isEmpty()) {
      boundSql = new BoundSql(configuration, boundSql.getSql(), parameterMap.getParameterMappings(), parameterObject);
    }

    // check for nested result maps in parameter mappings (issue #30)
    for (ParameterMapping pm : boundSql.getParameterMappings()) {
      String rmId = pm.getResultMapId();
      if (rmId != null) {
        ResultMap rm = configuration.getResultMap(rmId);
        if (rm != null) {
          hasNestedResultMaps |= rm.hasNestedResultMaps();
        }
      }
    }

    return boundSql;
  }
}

SqlSourceSQL源码

public interface SqlSource {

  BoundSql getBoundSql(Object parameterObject);

}

BoundSql

/**
 * 绑定的SQL,是从SqlSource而来,将动态内容都处理完成得到的SQL语句字符串,其中包括?,还有绑定的参数
 * 
 */
public class BoundSql {

  private String sql;
  private List<ParameterMapping> parameterMappings;
  private Object parameterObject;
  private Map<String, Object> additionalParameters;
  private MetaObject metaParameters;

  public BoundSql(Configuration configuration, String sql, List<ParameterMapping> parameterMappings, Object parameterObject) {
    this.sql = sql;
    this.parameterMappings = parameterMappings;
    this.parameterObject = parameterObject;
    this.additionalParameters = new HashMap<String, Object>();
    this.metaParameters = configuration.newMetaObject(additionalParameters);
  }

  public String getSql() {
    return sql;
  }

  public List<ParameterMapping> getParameterMappings() {
    return parameterMappings;
  }

  public Object getParameterObject() {
    return parameterObject;
  }

  public boolean hasAdditionalParameter(String name) {
    return metaParameters.hasGetter(name);
  }

  public void setAdditionalParameter(String name, Object value) {
    metaParameters.setValue(name, value);
  }

  public Object getAdditionalParameter(String name) {
    return metaParameters.getValue(name);
  }
}

MapperProxyFactory映射器代理工厂

/**
 * 映射器代理工厂
 */
public class MapperProxyFactory<T> {

  private final Class<T> mapperInterface;
  private Map<Method, MapperMethod> methodCache = new ConcurrentHashMap<Method, MapperMethod>();

  public MapperProxyFactory(Class<T> mapperInterface) {
    this.mapperInterface = mapperInterface;
  }

  public Class<T> getMapperInterface() {
    return mapperInterface;
  }

  public Map<Method, MapperMethod> getMethodCache() {
    return methodCache;
  }

  @SuppressWarnings("unchecked")
  protected T newInstance(MapperProxy<T> mapperProxy) {
    //用JDK自带的动态代理生成映射器
    return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
  }

  public T newInstance(SqlSession sqlSession) {
    final MapperProxy<T> mapperProxy = new MapperProxy<T>(sqlSession, mapperInterface, methodCache);
    return newInstance(mapperProxy);
  }

}