Mybatis-SqlSession源碼解析

Mybatis3.5.1源碼分析

  1. Mybatis-SqlSessionFactoryBuilder,XMLConfigBuilder,XPathParser源碼解析
  2. Mybatis-Configuration源碼解析
  3. Mybatis-事務(wù)對(duì)象源碼解析
  4. Mybatis-數(shù)據(jù)源源碼解析
  5. Mybatis緩存策略源碼解析
  6. Mybatis-DatabaseIdProvider源碼解析
  7. Mybatis-TypeHandler源碼解析
  8. Mybatis-Reflector源碼解析
  9. Mybatis-ObjectFactory,ObjectWrapperFactory源碼分析
  10. Mybatis-Mapper各類標(biāo)簽封裝類源碼解析
  11. Mybatis-XMLMapperBuilder,XMLStatmentBuilder源碼分析
  12. Mybatis-MapperAnnotationBuilder源碼分析
  13. [Mybatis-MetaObject,MetaClass源碼解析]http://www.itdecent.cn/p/f51fa552f30a)
  14. Mybatis-LanguageDriver源碼解析
  15. Mybatis-SqlSource源碼解析
  16. Mybatis-SqlNode源碼解析
  17. Mybatis-KeyGenerator源碼解析
  18. Mybatis-Executor源碼解析
  19. Mybatis-ParameterHandler源碼解析
  20. Mybatis-StatementHandler源碼解析
  21. Mybatis-DefaultResultSetHandler(一)源碼解析
  22. Mybatis-DefaultResultSetHandler(二)源碼解析
  23. Mybatis-ResultHandler,Cursor,RowBounds 源碼分析
  24. Mybatis-MapperProxy源碼解析
  25. Mybatis-SqlSession源碼解析
  26. Mybatis-Interceptor源碼解析

SqlSession

/**
 *    Copyright 2009-2019 the original author or authors.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */
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;

/**
 * The primary Java interface for working with MyBatis.
 * Through this interface you can execute commands, get mappers and manage transactions.
 * <p>
 *     數(shù)據(jù)庫對(duì)話
 * </p>
 * <p>
 *      這個(gè)Mybatis的主要Java接口,通過這個(gè)接口可以執(zhí)行命令,映射器和管理事務(wù)。
 * </p>
 * <p>
 *     Closeable:表示可以關(guān)閉的數(shù)據(jù)的源或目的地。 調(diào)用close方法來釋放對(duì)象持有的資源(如打開的文件)。
 * </p>
 * @author Clinton Begin
 */
public interface SqlSession extends Closeable {

  /**
   * Retrieve a single row mapped from the statement key. 返回單個(gè)查詢結(jié)果
   * @param <T> the returned object type  結(jié)果對(duì)象類型
   * @param statement 唯一標(biāo)識(shí)匹配的語句.
   * @return Mapped object 映射對(duì)象
   */
  <T> T selectOne(String statement);

  /**
   * Retrieve a single row mapped from the statement key and parameter.  返回單個(gè)查詢結(jié)果
   * @param <T> the returned object type  結(jié)果對(duì)象類型
   * @param statement Unique identifier matching the statement to use. 唯一標(biāo)識(shí)匹配的語句.
   * @param parameter A parameter object to pass to the statement. 查詢參數(shù)對(duì)象
   * @return Mapped object 映射對(duì)象
   */
  <T> T selectOne(String statement, Object parameter);

  /**
   * Retrieve a list of mapped objects from the statement key and parameter. 返回查詢結(jié)果集合
   * @param <E> the returned list element type 結(jié)果對(duì)象類型
   * @param statement Unique identifier matching the statement to use. 唯一標(biāo)識(shí)匹配的語句.
   * @return List of mapped object 映射對(duì)象集合
   */
  <E> List<E> selectList(String statement);

  /**
   * Retrieve a list of mapped objects from the statement key and parameter. 返回查詢結(jié)果集合
   * @param <E> the returned list element type 結(jié)果對(duì)象類型
   * @param statement Unique identifier matching the statement to use. 唯一標(biāo)識(shí)匹配的語句.
   * @param parameter A parameter object to pass to the statement. 查詢參數(shù)對(duì)象
   * @return List of mapped object  映射對(duì)象集合
   */
  <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. 返回集合結(jié)果
   * @param <E> the returned list element type 結(jié)果對(duì)象類型
   * @param statement Unique identifier matching the statement to use. 唯一標(biāo)識(shí)匹配的語句
   * @param parameter A parameter object to pass to the statement. 查詢參數(shù)對(duì)象
   * @param rowBounds  Bounds to limit object retrieval 返回結(jié)果的大小控制
   * @return List of mapped object 映射對(duì)象集合
   */
  <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.
   * 返回Map對(duì)象
   * Eg. Return a of Map[Integer,Author] for selectMap("selectAuthors","id")
   * @param <K> the returned Map keys type Map的Key類型
   * @param <V> the returned Map values type Map的Value類型
   * @param statement Unique identifier matching the statement to use. 唯一標(biāo)識(shí)匹配的語句.
   * @param mapKey The property to use as key for each value in the list. key值,字段的屬性別名
   * @return Map containing key pair data. 結(jié)果對(duì)象映射
   */
  <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對(duì)象
   * @param <K> the returned Map keys type Map的Key類型
   * @param <V> the returned Map values type Map的Value類型
   * @param statement Unique identifier matching the statement to use. 唯一標(biāo)識(shí)匹配的語句.
   * @param parameter A parameter object to pass to the statement. 查詢參數(shù)對(duì)象
   * @param mapKey The property to use as key for each value in the list. key值,字段的屬性別名
   * @return Map containing key pair data. 結(jié)果對(duì)象映射
   */
  <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對(duì)象
   * @param <K> the returned Map keys type Map的Key類型
   * @param <V> the returned Map values type  Map的Value類型
   * @param statement Unique identifier matching the statement to use.  唯一標(biāo)識(shí)匹配的語句.
   * @param parameter A parameter object to pass to the statement. 查詢參數(shù)對(duì)象
   * @param mapKey The property to use as key for each value in the list. key值,字段的屬性別名
   * @param rowBounds  Bounds to limit object retrieval 返回結(jié)果的大小控制
   * @return Map containing key pair data. 結(jié)果對(duì)象映射
   */
  <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey, RowBounds rowBounds);

  /**
   * A Cursor offers the same results as a List, except it fetches data lazily using an Iterator. 游標(biāo)查詢
   * @param <T> the returned cursor element type. 結(jié)果對(duì)象類型
   * @param statement Unique identifier matching the statement to use.  唯一標(biāo)識(shí)匹配的語句
   * @return Cursor of mapped objects 結(jié)果對(duì)象游標(biāo)
   */
  <T> Cursor<T> selectCursor(String statement);

  /**
   * A Cursor offers the same results as a List, except it fetches data lazily using an Iterator. 游標(biāo)查詢
   * @param <T> the returned cursor element type. 結(jié)果對(duì)象類型
   * @param statement Unique identifier matching the statement to use.  唯一標(biāo)識(shí)匹配的語句
   * @param parameter A parameter object to pass to the statement.查詢參數(shù)對(duì)象
   * @return Cursor of mapped objects  結(jié)果對(duì)象游標(biāo)
   */
  <T> Cursor<T> selectCursor(String statement, Object parameter);

  /**
   * A Cursor offers the same results as a List, except it fetches data lazily using an Iterator. 游標(biāo)查詢
   * @param <T> the returned cursor element type. 結(jié)果對(duì)象類型
   * @param statement Unique identifier matching the statement to use. 唯一標(biāo)識(shí)匹配的語句
   * @param parameter A parameter object to pass to the statement. 查詢參數(shù)對(duì)象
   * @param rowBounds  Bounds to limit object retrieval 返回結(jié)果的大小控制
   * @return Cursor of mapped objects 結(jié)果對(duì)象游標(biāo)
   */
  <T> Cursor<T> selectCursor(String statement, Object parameter, RowBounds rowBounds);

  /**
   * Retrieve a single row mapped from the statement key and parameter
   * using a {@code ResultHandler}. 查詢單條,用ResultHandler接收結(jié)果
   * @param statement Unique identifier matching the statement to use.  唯一標(biāo)識(shí)匹配的語句
   * @param parameter A parameter object to pass to the statement. 查詢參數(shù)對(duì)象
   * @param handler ResultHandler that will handle each retrieved row 結(jié)果接收處理器
   */
  void select(String statement, Object parameter, ResultHandler handler);

  /**
   * Retrieve a single row mapped from the statement
   * using a {@code ResultHandler}. 查詢單條,用ResultHandler接收結(jié)果
   * @param statement Unique identifier matching the statement to use. 唯一標(biāo)識(shí)匹配的語句
   * @param handler ResultHandler that will handle each retrieved row 結(jié)果接收處理器
   */
  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接收結(jié)果
   * @param statement Unique identifier matching the statement to use. 唯一標(biāo)識(shí)匹配的語句
   * @param rowBounds RowBound instance to limit the query results 返回結(jié)果的大小控制
   * @param handler ResultHandler that will handle each retrieved row 結(jié)果接收處理器
   */
  void select(String statement, Object parameter, RowBounds rowBounds, ResultHandler handler);

  /**
   * Execute an insert statement. 執(zhí)行插入SQL
   * @param statement Unique identifier matching the statement to execute. 唯一標(biāo)識(shí)匹配的語句
   * @return int The number of rows affected by the insert. 更新記錄數(shù)
   */
  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. 執(zhí)行插入SQL
   * @param statement Unique identifier matching the statement to execute. 唯一標(biāo)識(shí)匹配的語句
   * @param parameter A parameter object to pass to the statement. 插入?yún)?shù)對(duì)象
   * @return int The number of rows affected by the insert. 更新記錄數(shù)
   */
  int insert(String statement, Object parameter);

  /**
   * Execute an update statement. The number of rows affected will be returned. 執(zhí)行修改SQL
   * @param statement Unique identifier matching the statement to execute. 唯一標(biāo)識(shí)匹配的語句
   * @return int The number of rows affected by the update.更新記錄數(shù)
   */
  int update(String statement);

  /**
   * Execute an update statement. The number of rows affected will be returned. 執(zhí)行修改SQL
   * @param statement Unique identifier matching the statement to execute. 唯一標(biāo)識(shí)匹配的語句
   * @param parameter A parameter object to pass to the statement.  修改參數(shù)對(duì)象
   * @return int The number of rows affected by the update. .更新記錄數(shù)
   */
  int update(String statement, Object parameter);

  /**
   * Execute a delete statement. The number of rows affected will be returned. 執(zhí)行刪除SQL
   * @param statement Unique identifier matching the statement to execute.唯一標(biāo)識(shí)匹配的語句
   * @return int The number of rows affected by the delete. 更新記錄數(shù)
   */
  int delete(String statement);

  /**
   * Execute a delete statement. The number of rows affected will be returned. 執(zhí)行delete語句。將返回受影響的行數(shù);
   * @param statement Unique identifier matching the statement to execute. 唯一標(biāo)識(shí)匹配的語句
   * @param parameter A parameter object to pass to the statement. 刪除參數(shù)對(duì)象
   * @return int The number of rows affected by the delete. 更新記錄數(shù)
   */
  int delete(String statement, Object parameter);

  /**
   * Flushes batch statements and commits database connection. 事務(wù)提交
   * Note that database connection will not be committed if no updates/deletes/inserts were called. 注意,數(shù)據(jù)庫連接將不會(huì)提交如果沒有更新/刪除/插入被稱為。;
   * To force the commit call {@link SqlSession#commit(boolean)} 如果需要強(qiáng)制提交,可以調(diào)用 {@link SqlSession#commit(boolean)}
   */
  void commit();

  /**
   * Flushes batch statements and commits database connection. 事務(wù)提交
   * @param force forces connection commit 強(qiáng)制提交數(shù)據(jù)庫連接
   */
  void commit(boolean force);

  /**
   * Discards pending batch statements and rolls database connection back. 事務(wù)回退
   * Note that database connection will not be rolled back if no updates/deletes/inserts were called. 注意,數(shù)據(jù)庫連接將不會(huì)回退如果沒有更新/刪除/插入被調(diào)用;
   * To force the rollback call {@link SqlSession#rollback(boolean)} 如果需要強(qiáng)制回退,可以調(diào)用 {@link SqlSession#commit(boolean)}
   */
  void rollback();

  /**
   * Discards pending batch statements and rolls database connection back. 事務(wù)回退;
   * Note that database connection will not be rolled back if no updates/deletes/inserts were called.注意,數(shù)據(jù)庫連接將不會(huì)回退如果沒有更新/刪除/插入被稱為。;
   * @param force forces connection rollback 強(qiáng)制回退數(shù)據(jù)庫連接
   */
  void rollback(boolean force);

  /**
   * Flushes batch statements.執(zhí)行全部等待批處理語句,并將結(jié)果封裝到BatchResult集合中
   * @return BatchResult list of updated records 更新記錄的BatchResult集合
   * @since 3.0.6
   */
  List<BatchResult> flushStatements();

  /**
   * Closes the session. 關(guān)閉數(shù)據(jù)庫對(duì)話
   */
  @Override
  void close();

  /**
   * Clears local session cache. 清空數(shù)據(jù)庫對(duì)話緩存
   */
  void clearCache();

  /**
   * 獲取Mybatis全局配置信息
   * Retrieves current configuration.
   * @return Configuration
   */
  Configuration getConfiguration();

  /**
   * Retrieves a mapper. 獲取Mapper
   * @param <T> the mapper type  Mapper對(duì)應(yīng)的Class類型
   * @param type Mapper interface class Mapper對(duì)應(yīng)的Class類型
   * @return a mapper bound to this SqlSession 一個(gè)綁定到這個(gè)Sql會(huì)話的Mapper;
   */
  <T> T getMapper(Class<T> type);

  /**
   * Retrieves inner database connection. 獲取數(shù)據(jù)庫連接
   * @return Connection
   */
  Connection getConnection();
}

DefaultSqlSession

/**
 *    Copyright 2009-2019 the original author or authors.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */
package org.apache.ibatis.session.defaults;

import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.ibatis.binding.BindingException;
import org.apache.ibatis.cursor.Cursor;
import org.apache.ibatis.exceptions.ExceptionFactory;
import org.apache.ibatis.exceptions.TooManyResultsException;
import org.apache.ibatis.executor.BatchResult;
import org.apache.ibatis.executor.ErrorContext;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.executor.result.DefaultMapResultHandler;
import org.apache.ibatis.executor.result.DefaultResultContext;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.apache.ibatis.session.SqlSession;

/**
 * The default implementation for {@link SqlSession}. 這是一個(gè)SqlSession接口的默認(rèn)實(shí)現(xiàn)類
 * Note that this class is not Thread-Safe. 注意,這個(gè)類并不是線程安全的
 *
 * @author Clinton Begin
 */
public class DefaultSqlSession implements SqlSession {

  /**
   * mybatis全局配置新
   */
  private final Configuration configuration;
  /**
   * SQL腳本執(zhí)行器
   */
  private final Executor executor;

  /**
   * 是否自動(dòng)提交
   */
  private final boolean autoCommit;
  /**
   * 是否有調(diào)用更新SQL腳本標(biāo)記
   */
  private boolean dirty;
  /**
   * 游標(biāo)集合
   */
  private List<Cursor<?>> cursorList;

  /**
   *
   * @param configuration mybatis全局配置信息
   * @param executor SQL腳本執(zhí)行器
   * @param autoCommit 是否自動(dòng)提交標(biāo)記
   */
  public DefaultSqlSession(Configuration configuration, Executor executor, boolean autoCommit) {
    this.configuration = configuration;
    this.executor = executor;
    this.dirty = false;
    this.autoCommit = autoCommit;
  }

  /**
   *
   * @param configuration Mybatis全局配置信息
   * @param executor SQL腳本執(zhí)行器
   */
  public DefaultSqlSession(Configuration configuration, Executor executor) {
    //不設(shè)置自動(dòng)提交
    this(configuration, executor, false);
  }

  /**
   * 返回單個(gè)查詢結(jié)果
   * @param statement 唯一標(biāo)識(shí)匹配的語句.
   * @param <T> 結(jié)果對(duì)象類型
   * @return 映射對(duì)象
   */
  @Override
  public <T> T selectOne(String statement) {
    return this.selectOne(statement, null);
  }

  /**
   * 返回單個(gè)查詢結(jié)果
   * @param statement Unique identifier matching the statement to use. 唯一標(biāo)識(shí)匹配的語句.
   * @param parameter A parameter object to pass to the statement. 查詢參數(shù)對(duì)象
   * @param <T> 結(jié)果對(duì)象類型
   * @return 映射對(duì)象
   */
  @Override
  public <T> T selectOne(String statement, Object parameter) {
    // Popular vote was to return null on 0 results and throw exception on too many.
    // 民眾投票 當(dāng)沒有結(jié)果對(duì)象時(shí),返回null;當(dāng)超過1條結(jié)果對(duì)象時(shí),拋出異常
    List<T> list = this.selectList(statement, parameter);
    //如果一個(gè)結(jié)果對(duì)象在集合中
    if (list.size() == 1) {
      //返回這個(gè)結(jié)果對(duì)象
      return list.get(0);
      //如果出現(xiàn)超過一個(gè)結(jié)果對(duì)象在集合中
    } else if (list.size() > 1) {
      //拋出異常
      throw new TooManyResultsException("Expected one result (or null) to be returned by selectOne(), but found: " + list.size());
      //如果沒有結(jié)果對(duì)象在集合中
    } else {
      //返回null
      return null;
    }
  }

  /**
   * 返回Map對(duì)象
   * @param statement Unique identifier matching the statement to use. 唯一標(biāo)識(shí)匹配的語句.
   * @param mapKey The property to use as key for each value in the list. key值,字段的屬性別名
   * @param <K> Map的Key類型
   * @param <V> Map的Value類型
   * @return 結(jié)果對(duì)象映射
   */
  @Override
  public <K, V> Map<K, V> selectMap(String statement, String mapKey) {
    //RowBounds.DEFAULT:從0開始到Integer.MAX_VALUE
    return this.selectMap(statement, null, mapKey, RowBounds.DEFAULT);
  }

  /**
   * 返回Map對(duì)象
   * @param statement Unique identifier matching the statement to use. 唯一標(biāo)識(shí)匹配的語句.
   * @param parameter A parameter object to pass to the statement. 查詢參數(shù)對(duì)象
   * @param mapKey The property to use as key for each value in the list. key值,字段的屬性別名
   * @param <K> Map的Key類型
   * @param <V> Map的Value類型
   * @return 結(jié)果對(duì)象映射
   */
  @Override
  public <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey) {
    //RowBounds.DEFAULT:從0開始到Integer.MAX_VALUE
    return this.selectMap(statement, parameter, mapKey, RowBounds.DEFAULT);
  }

  /**
   * 返回Map對(duì)象
   * @param statement Unique identifier matching the statement to use.  唯一標(biāo)識(shí)匹配的語句.
   * @param parameter A parameter object to pass to the statement. 查詢參數(shù)對(duì)象
   * @param mapKey The property to use as key for each value in the list. key值,字段的屬性別名
   * @param rowBounds  Bounds to limit object retrieval 返回結(jié)果的大小控制
   * @param <K> Map的Key類型
   * @param <V>  Map的Value類型
   * @return 結(jié)果對(duì)象映射
   */
  @Override
  public <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey, RowBounds rowBounds) {
    //執(zhí)行查詢SQL腳本,返回結(jié)果對(duì)象集合
    final List<? extends V> list = selectList(statement, parameter, rowBounds);
    //新建一個(gè)默認(rèn)Map形式的ResultHandler
    final DefaultMapResultHandler<K, V> mapResultHandler = new DefaultMapResultHandler<>(mapKey,
            configuration.getObjectFactory(), configuration.getObjectWrapperFactory(), configuration.getReflectorFactory());
    //新建一個(gè)默認(rèn)結(jié)果上下文:這個(gè)類封裝了結(jié)果集個(gè)數(shù)和當(dāng)前結(jié)果
    final DefaultResultContext<V> context = new DefaultResultContext<>();
    //遍歷結(jié)果對(duì)象集合
    for (V o : list) {
      //將結(jié)果對(duì)象賦值到結(jié)果上下文的下一個(gè)結(jié)果對(duì)象中
      context.nextResultObject(o);
      //接收結(jié)果上下文,取出結(jié)果對(duì)象,添加到mapResultHandler內(nèi)部維護(hù)的Map對(duì)象中
      mapResultHandler.handleResult(context);
    }
    //返回mapResultHandler內(nèi)部維護(hù)的Map對(duì)象
    return mapResultHandler.getMappedResults();
  }

  /**
   * 游標(biāo)查詢
   * @param statement Unique identifier matching the statement to use.  唯一標(biāo)識(shí)匹配的語句
   * @param <T> 結(jié)果對(duì)象類型
   * @return 結(jié)果對(duì)象游標(biāo)
   */
  @Override
  public <T> Cursor<T> selectCursor(String statement) {
    return selectCursor(statement, null);
  }

  /**
   * 游標(biāo)查詢
   * @param statement Unique identifier matching the statement to use.  唯一標(biāo)識(shí)匹配的語句
   * @param parameter A parameter object to pass to the statement.查詢參數(shù)對(duì)象
   * @param <T> 結(jié)果對(duì)象類型
   * @return 結(jié)果對(duì)象游標(biāo)
   */
  @Override
  public <T> Cursor<T> selectCursor(String statement, Object parameter) {
    //RowBounds.DEFAULT:從0開始到Integer.MAX_VALUE
    return selectCursor(statement, parameter, RowBounds.DEFAULT);
  }

  /**
   * 游標(biāo)查詢
   * @param statement Unique identifier matching the statement to use. 唯一標(biāo)識(shí)匹配的語句
   * @param parameter A parameter object to pass to the statement. 查詢參數(shù)對(duì)象
   * @param rowBounds  Bounds to limit object retrieval 返回結(jié)果的大小控制
   * @param <T> 結(jié)果對(duì)象類型
   * @return  結(jié)果對(duì)象游標(biāo)
   */
  @Override
  public <T> Cursor<T> selectCursor(String statement, Object parameter, RowBounds rowBounds) {
    try {
      //MappedStatement: Mapper.xml文件的select,delete,update,insert這些DML標(biāo)簽的封裝類
      //獲取statement對(duì)應(yīng)的MappedStatment對(duì)象
      MappedStatement ms = configuration.getMappedStatement(statement);
      /**
       * 如果{@code object}是數(shù)組,或者是Collection實(shí)現(xiàn)類,會(huì)將 {@code object} 包裝成StrictMap對(duì)象,
       * 否則直接返回 {@code object},執(zhí)行查詢,返回結(jié)果對(duì)象游標(biāo)
       */
      Cursor<T> cursor = executor.queryCursor(ms, wrapCollection(parameter), rowBounds);
      //注冊(cè)游標(biāo),將cursor添加到cursorList中
      registerCursor(cursor);
      //返回結(jié)果對(duì)象游標(biāo)
      return cursor;
    } catch (Exception e) {
      //如果出現(xiàn)異常,就包裝異常對(duì)象,并加以描述再拋出
      throw ExceptionFactory.wrapException("Error querying database.  Cause: " + e, e);
    } finally {
      //錯(cuò)誤上下文實(shí)例重置
      ErrorContext.instance().reset();
    }
  }

  /**
   * 返回查詢結(jié)果集合
   * @param statement Unique identifier matching the statement to use. 唯一標(biāo)識(shí)匹配的語句.
   * @param <E> 結(jié)果對(duì)象類型
   * @return 映射對(duì)象集合
   */
  @Override
  public <E> List<E> selectList(String statement) {
    return this.selectList(statement, null);
  }

  /**
   * 返回查詢結(jié)果集合
   * @param statement Unique identifier matching the statement to use. 唯一標(biāo)識(shí)匹配的語句.
   * @param parameter A parameter object to pass to the statement. 查詢參數(shù)對(duì)象
   * @param <E> 結(jié)果對(duì)象類型
   * @return 映射對(duì)象集合
   */
  @Override
  public <E> List<E> selectList(String statement, Object parameter) {
    //RowBounds.DEFAULT:從0開始到Integer.MAX_VALUE
    return this.selectList(statement, parameter, RowBounds.DEFAULT);
  }

  /**
   * 返回集合結(jié)果
   * @param statement Unique identifier matching the statement to use. 唯一標(biāo)識(shí)匹配的語句
   * @param parameter A parameter object to pass to the statement. 查詢參數(shù)對(duì)象
   * @param rowBounds  Bounds to limit object retrieval 返回結(jié)果的大小控制
   * @param <E> 結(jié)果對(duì)象類型
   * @return 結(jié)果對(duì)象集合
   */
  @Override
  public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
    try {
      //MappedStatement: Mapper.xml文件的select,delete,update,insert這些DML標(biāo)簽的封裝類
      //獲取statement對(duì)應(yīng)的MappedStatment對(duì)象
      MappedStatement ms = configuration.getMappedStatement(statement);
      /**
       * 如果{@code object}是數(shù)組,或者是Collection實(shí)現(xiàn)類,會(huì)將 {@code object} 包裝成StrictMap對(duì)象,
       * 否則直接返回 {@code object},執(zhí)行查詢,返回結(jié)果對(duì)象集合
       */
      return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);
    } catch (Exception e) {
      //如果出現(xiàn)異常,就包裝異常對(duì)象,并加以描述再拋出
      throw ExceptionFactory.wrapException("Error querying database.  Cause: " + e, e);
    } finally {
      //錯(cuò)誤上下文實(shí)例重置
      ErrorContext.instance().reset();
    }
  }

  /**
   * 查詢單條,用ResultHandler接收結(jié)果
   * @param statement Unique identifier matching the statement to use.  唯一標(biāo)識(shí)匹配的語句
   * @param parameter A parameter object to pass to the statement. 查詢參數(shù)對(duì)象
   * @param handler ResultHandler that will handle each retrieved row 結(jié)果接收處理器
   */
  @Override
  public void select(String statement, Object parameter, ResultHandler handler) {
    //RowBounds.DEFAULT:從0開始到Integer.MAX_VALUE
    select(statement, parameter, RowBounds.DEFAULT, handler);
  }

  /**
   * 查詢單條,用ResultHandler接收結(jié)果
   * @param statement Unique identifier matching the statement to use. 唯一標(biāo)識(shí)匹配的語句
   * @param handler ResultHandler that will handle each retrieved row 結(jié)果接收處理器
   */
  @Override
  public void select(String statement, ResultHandler handler) {
    //RowBounds.DEFAULT:從0開始到Integer.MAX_VALUE
    select(statement, null, RowBounds.DEFAULT, handler);
  }

  /**
   * 查詢單條,用ResultHandler接收結(jié)果
   * @param statement Unique identifier matching the statement to use. 唯一標(biāo)識(shí)匹配的語句
   * @param parameter 參數(shù)對(duì)象
   * @param rowBounds RowBound instance to limit the query results 返回結(jié)果的大小控制
   * @param handler ResultHandler that will handle each retrieved row 結(jié)果接收處理器
   */
  @Override
  public void select(String statement, Object parameter, RowBounds rowBounds, ResultHandler handler) {
    try {
      //MappedStatement: Mapper.xml文件的select,delete,update,insert這些DML標(biāo)簽的封裝類
      //獲取statement對(duì)應(yīng)的MappedStatment對(duì)象
      MappedStatement ms = configuration.getMappedStatement(statement);
      /**
       * 如果parameter是數(shù)組,或者是Collection實(shí)現(xiàn)類,會(huì)將parameter 包裝成StrictMap對(duì)象,
       * 否則直接返回parameter,執(zhí)行查詢,用handler接收結(jié)果對(duì)象
       */
      executor.query(ms, wrapCollection(parameter), rowBounds, handler);
    } catch (Exception e) {
      //如果出現(xiàn)異常,就包裝異常對(duì)象,并加以描述再拋出
      throw ExceptionFactory.wrapException("Error querying database.  Cause: " + e, e);
    } finally {
      //錯(cuò)誤上下文實(shí)例重置
      ErrorContext.instance().reset();
    }
  }

  /**
   * 執(zhí)行插入SQL
   * @param statement Unique identifier matching the statement to execute. 唯一標(biāo)識(shí)匹配的語句
   * @return 更新記錄數(shù)
   */
  @Override
  public int insert(String statement) {
    return insert(statement, null);
  }

  /**
   * 執(zhí)行插入SQL
   * @param statement Unique identifier matching the statement to execute. 唯一標(biāo)識(shí)匹配的語句
   * @param parameter A parameter object to pass to the statement. 插入?yún)?shù)對(duì)象
   * @return 更新記錄數(shù)
   */
  @Override
  public int insert(String statement, Object parameter) {
    return update(statement, parameter);
  }

  /**
   * 執(zhí)行修改SQL
   * @param statement Unique identifier matching the statement to execute. 唯一標(biāo)識(shí)匹配的語句
   * @return 更新記錄數(shù)
   */
  @Override
  public int update(String statement) {
    return update(statement, null);
  }

  /**
   * 執(zhí)行修改SQL
   * @param statement Unique identifier matching the statement to execute. 唯一標(biāo)識(shí)匹配的語句
   * @param parameter A parameter object to pass to the statement.  修改參數(shù)對(duì)象
   * @return 更新記錄數(shù)
   */
  @Override
  public int update(String statement, Object parameter) {
    try {
      //將是否有調(diào)用更新SQL標(biāo)記設(shè)置為true,表示有有調(diào)用更新SQL
      dirty = true;
      //MappedStatement: Mapper.xml文件的select,delete,update,insert這些DML標(biāo)簽的封裝類
      //獲取statement對(duì)應(yīng)的MappedStatment對(duì)象
      MappedStatement ms = configuration.getMappedStatement(statement);
      /**
       * wrapCollection:如果parameter是數(shù)組,或者是Collection實(shí)現(xiàn)類,會(huì)將parameter 包裝成StrictMap對(duì)象,
       * 否則直接返回parameter
       */
      //執(zhí)行更新SQL腳本
      return executor.update(ms, wrapCollection(parameter));
    } catch (Exception e) {
      //如果出現(xiàn)異常,就包裝異常對(duì)象,并加以描述再拋出
      throw ExceptionFactory.wrapException("Error updating database.  Cause: " + e, e);
    } finally {
      //錯(cuò)誤上下文實(shí)例重置
      ErrorContext.instance().reset();
    }
  }

  /**
   * 執(zhí)行刪除SQL
   * @param statement Unique identifier matching the statement to execute.唯一標(biāo)識(shí)匹配的語句
   * @return 更新記錄數(shù)
   */
  @Override
  public int delete(String statement) {
    return update(statement, null);
  }

  /**
   * 執(zhí)行刪除SQL
   * @param statement Unique identifier matching the statement to execute. 唯一標(biāo)識(shí)匹配的語句
   * @param parameter A parameter object to pass to the statement. 刪除參數(shù)對(duì)象
   * @return 更新記錄數(shù)
   */
  @Override
  public int delete(String statement, Object parameter) {
    return update(statement, parameter);
  }

  /**
   * 事務(wù)提交
   * <p>
   *     注意,數(shù)據(jù)庫連接將不會(huì)提交如果沒有更新/刪除/插入被稱為。
   *     如果需要強(qiáng)制提交,可以調(diào)用 {@link SqlSession#commit(boolean)}
   * </p>
   */
  @Override
  public void commit() {
    commit(false);
  }

  /**
   * 事務(wù)提交
   * @param force forces connection commit 強(qiáng)制提交數(shù)據(jù)庫連接
   */
  @Override
  public void commit(boolean force) {
    try {
      /**
       * isCommitOrRollbackRequired:只要force為true,一定返回ture;如果force
       * 為false,如果沒有設(shè)置自動(dòng)提交但有執(zhí)行更新的SQL腳本;否則返回false
       */
      //通知執(zhí)行器提交事務(wù)
      executor.commit(isCommitOrRollbackRequired(force));
      //事務(wù)結(jié)束,標(biāo)記還原
      dirty = false;
    } catch (Exception e) {
      //如果出現(xiàn)異常,就包裝異常對(duì)象,并加以描述再拋出
      throw ExceptionFactory.wrapException("Error committing transaction.  Cause: " + e, e);
    } finally {
      //錯(cuò)誤上下文實(shí)例重置
      ErrorContext.instance().reset();
    }
  }

  /**
   * 事務(wù)回退
   * <p>
   *     注意,數(shù)據(jù)庫連接將不會(huì)回退如果沒有更新/刪除/插入被調(diào)用;
   *     如果需要強(qiáng)制回退,可以調(diào)用 {@link SqlSession#commit(boolean)}
   * </p>
   */
  @Override
  public void rollback() {
    rollback(false);
  }

  /**
   * 事務(wù)回退
   * @param force forces connection rollback 強(qiáng)制回退數(shù)據(jù)庫連接
   */
  @Override
  public void rollback(boolean force) {
    try {
      /**
       * isCommitOrRollbackRequired:只要force為true,一定返回ture;如果force
       * 為false,如果沒有設(shè)置自動(dòng)提交但有執(zhí)行更新的SQL腳本;否則返回false
       */
      //通知執(zhí)行器回退事務(wù)
      executor.rollback(isCommitOrRollbackRequired(force));
      //事務(wù)結(jié)束,標(biāo)記還原
      dirty = false;
    } catch (Exception e) {
      //如果出現(xiàn)異常,就包裝異常對(duì)象,并加以描述再拋出
      throw ExceptionFactory.wrapException("Error rolling back transaction.  Cause: " + e, e);
    } finally {
      //錯(cuò)誤上下文實(shí)例重置
      ErrorContext.instance().reset();
    }
  }

  /**
   * 執(zhí)行全部等待批處理語句,并將結(jié)果封裝到BatchResult集合中
   * @return 更新記錄的BatchResult集合
   */
  @Override
  public List<BatchResult> flushStatements() {
    try {
      //通知執(zhí)行器執(zhí)行全部等待批處理語句,并將結(jié)果封裝到BatchResult集合中
      return executor.flushStatements();
    } catch (Exception e) {
      //如果出現(xiàn)異常,就包裝異常對(duì)象,并加以描述再拋出
      throw ExceptionFactory.wrapException("Error flushing statements.  Cause: " + e, e);
    } finally {
      //錯(cuò)誤上下文實(shí)例重置
      ErrorContext.instance().reset();
    }
  }

  @Override
  public void close() {
    try {
      /**
       * isCommitOrRollbackRequired:只要force為true,一定返回ture;如果force
       * 為false,如果沒有設(shè)置自動(dòng)提交但有執(zhí)行更新的SQL腳本;否則返回false
       */
      //關(guān)閉執(zhí)行器,回退事務(wù),關(guān)閉事務(wù)
      executor.close(isCommitOrRollbackRequired(false));
      //關(guān)閉游標(biāo)集合中的所有游標(biāo)對(duì)象,清空游標(biāo)集合
      closeCursors();
      //標(biāo)記還原
      dirty = false;
    } finally {
      //錯(cuò)誤上下文實(shí)例重置
      ErrorContext.instance().reset();
    }
  }

  /**
   * 關(guān)閉游標(biāo)集合中的所有游標(biāo)對(duì)象,清空游標(biāo)集合
   */
  private void closeCursors() {
    //如果游標(biāo)集合不為null且游標(biāo)集合不是空集合
    if (cursorList != null && cursorList.size() != 0) {
      //遍歷游標(biāo)集合
      for (Cursor<?> cursor : cursorList) {
        try {
          //關(guān)閉游標(biāo)
          cursor.close();
        } catch (IOException e) {
          //如果出現(xiàn)異常,就包裝異常對(duì)象,并加以描述再拋出
          throw ExceptionFactory.wrapException("Error closing cursor.  Cause: " + e, e);
        }
      }
      //清空游標(biāo)集合中的所有游標(biāo)
      cursorList.clear();
    }
  }

  /**
   * 獲取Mybatis全局配置信息
   * @return Mybatis全局配置信息對(duì)象
   */
  @Override
  public Configuration getConfiguration() {
    return configuration;
  }

  /**
   * 獲取Mapper
   * @param type Mapper interface class Mapper對(duì)應(yīng)的Class類型
   * @param <T> Mapper對(duì)應(yīng)的Class類型
   * @return 一個(gè)綁定到這個(gè)Sql會(huì)話的Mapper;
   */
  @Override
  public <T> T getMapper(Class<T> type) {
    return configuration.getMapper(type, this);
  }

  /**
   * 獲取數(shù)據(jù)庫連接
   * @return 數(shù)據(jù)庫連接對(duì)象
   */
  @Override
  public Connection getConnection() {
    try {
      //從執(zhí)行器中獲取事務(wù)對(duì)象,再從事務(wù)對(duì)象中獲取數(shù)據(jù)庫連接并返回
      return executor.getTransaction().getConnection();
    } catch (SQLException e) {
      ////如果出現(xiàn)異常,就包裝異常對(duì)象,并加以描述再拋出
      throw ExceptionFactory.wrapException("Error getting a new connection.  Cause: " + e, e);
    }
  }

  /**
   * 清空數(shù)據(jù)庫對(duì)話緩存
   */
  @Override
  public void clearCache() {
    //清空?qǐng)?zhí)行器本地緩存(一級(jí)緩存)
    executor.clearLocalCache();
  }

  /**
   * 注冊(cè)游標(biāo),將 {@code cursor} 添加到cursorList中
   * @param cursor 結(jié)果對(duì)象游標(biāo)
   * @param <T> 結(jié)果對(duì)象類型
   */
  private <T> void registerCursor(Cursor<T> cursor) {
    //如果游標(biāo)集合為null
    if (cursorList == null) {
      //實(shí)例化cursorList為ArrayList
      cursorList = new ArrayList<>();
    }
    //添加cursor到游標(biāo)對(duì)象集合中
    cursorList.add(cursor);
  }

  /**
   * 是否必須提交或者回滾
   * @param force 是否強(qiáng)制提交或者強(qiáng)制關(guān)閉
   * @return 只要force為true,一定返回ture;如果 {@code force} 為false,如果沒有設(shè)置自動(dòng)提交但有執(zhí)行更新的SQL腳本;否則返回false
   */
  private boolean isCommitOrRollbackRequired(boolean force) {
    //只要force為true,一定返回ture
    //如果force為false,如果沒有設(shè)置自動(dòng)提交但有執(zhí)行更新的SQL腳本,返回true;否則返回false
    return (!autoCommit && dirty) || force;
  }

  /**
   * 如果{@code object}是數(shù)組,或者是Collection實(shí)現(xiàn)類,會(huì)將 {@code object} 包裝成StrictMap對(duì)象,否則直接返回 {@code object}
   * @param object 參數(shù)對(duì)象
   * @return 如果object是數(shù)組,或者是Collection的實(shí)現(xiàn)類,就直接返回StrictMap對(duì)象;否則直接返回 {@code object}
   */
  private Object wrapCollection(final Object object) {
    //如果Object是Collection的實(shí)現(xiàn)類
    if (object instanceof Collection) {
      //StrictMap:HashMap的子類,對(duì)獲取集合沒有元素時(shí)會(huì)拋出異常。
      //新建一個(gè)Map
      StrictMap<Object> map = new StrictMap<>();
      //將object添加到map,key為collection
      map.put("collection", object);
      //如果object還是List的實(shí)現(xiàn)類
      if (object instanceof List) {
        //將object再次添加到map,key為list
        map.put("list", object);
      }
      return map;
      //如果object不為null,且 object是數(shù)組
    } else if (object != null && object.getClass().isArray()) {
      //StrictMap:HashMap的子類,對(duì)獲取集合沒有元素時(shí)會(huì)拋出異常。
      //新建一個(gè)Map
      StrictMap<Object> map = new StrictMap<>();
      //將object再次添加到map,key為array
      map.put("array", object);
      return map;
    }
    //如果object不是數(shù)組,又不是Collection的實(shí)現(xiàn)類,就直接返回object
    return object;
  }

  /**
   * HashMap的子類,對(duì)獲取集合沒有元素時(shí)會(huì)拋出異常。
   */
  public static class StrictMap<V> extends HashMap<String, V> {

    private static final long serialVersionUID = -5741767162221585340L;

    @Override
    public V get(Object key) {
      //如果沒有key對(duì)應(yīng)的value時(shí)
      if (!super.containsKey(key)) {
        throw new BindingException("Parameter '" + key + "' not found. Available parameters are " + this.keySet());
      }
      return super.get(key);
    }

  }

}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容