Mybatis源碼分析[04.SqlSession]

/**
 * 這是MyBatis用來執行SQL的類,獲取映射器,管理事務
 *
 */
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爲了擴展性,僅僅支持內存分頁。也就是會先把
   * 所有的數據查詢出來以後,然後在內存中進行分頁。因此在實際的情況中,需要注意
   * 這一點。
   *
   * @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.
   * 插入記錄。
   * @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();
}

SqlSession是一個接口類,其實際實現類爲DefaultSqlSession

// DefaultSqlSession屬性
public class DefaultSqlSession implements SqlSession {

  private Configuration configuration;
  private Executor executor;

  /**
   * 是否自動提交
   */
  private boolean autoCommit;
  private boolean dirty;
}

DefaultSqlSession最爲關鍵的是Executor executor,Executor爲一個接口類,DefaultSqlSession對外提供的接口,內部均調用Executor 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);

}

在mybatis源碼中,Executor的子類爲BaseExecutor,BaseExecutor是執行器的基類

public abstract class BaseExecutor implements Executor {

  private static final Log log = LogFactory.getLog(BaseExecutor.class);

  protected Transaction transaction;
  protected Executor wrapper;

  //延遲加載隊列(線程安全)
  protected ConcurrentLinkedQueue<DeferredLoad> deferredLoads;
  //本地緩存機制(Local Cache)防止循環引用(circular references)和加速重複嵌套查詢(一級緩存)
  //本地緩存
  protected PerpetualCache localCache;
  //本地輸出參數緩存
  protected PerpetualCache localOutputParameterCache;
  protected Configuration configuration;

  //查詢堆棧
  protected int queryStack = 0;
  private boolean closed;
}

BatchExecutor、CachingExecutor、ReuseExecutor、SimpleExecutor都是BaseExecutor的子類

  • BatchExecutor
// 批量操作執行器
public class BatchExecutor extends BaseExecutor {

  public static final int BATCH_UPDATE_RETURN_VALUE = Integer.MIN_VALUE + 1002;

  private final List<Statement> statementList = new ArrayList<Statement>();
  private final List<BatchResult> batchResultList = new ArrayList<BatchResult>();
  private String currentSql;
  private MappedStatement currentStatement;
}
  • CachingExecutor
// 緩存執行器
public class CachingExecutor implements Executor {

  private Executor delegate;
  private TransactionalCacheManager tcm = new TransactionalCacheManager();
}
  • ReuseExecutor
// 可重用執行器
public class ReuseExecutor extends BaseExecutor {

  //可重用的執行器內部用了一個map,key爲執行的sql,value爲sql對應的Statement
  private final Map<String, Statement> statementMap = new HashMap<String, Statement>();
}
  • SimpleExecutor
// 簡單執行器
public class SimpleExecutor extends BaseExecutor {
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章