Mybatis學習筆記(四):Mybatis運行原理解析

SqlSessionFactoryBuilder階段

在程序中第一步就是創建SqlSessionFactoryBuilder對象,調用它的build方法,將全局配置文件傳入,該方法便會返回一個SqlSessionFactory對象

		String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

在build方法中主要做的工作就是創建XMLConfigBuilder對象,用此對象解析全局配置文件,將解析到的信息封裝到Configuration對象中,並將此對象返回,接着這個Configuration對象會被當做DefaultSqlSessionFactory構造參數傳入,DefaultSqlSessionFactory根據Configuration對象中的信息創建SqlSessionFactory(類似於JDBC中根據用戶名、密碼、url等參數創建連接池一樣)。

public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
      XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
      return build(parser.parse())}
  public SqlSessionFactory build(Configuration config) {
    return new DefaultSqlSessionFactory(config);
  }

在這裏可以看到SqlSessionFactory是一個接口,默認使用的是DefaultSqlSessionFactory對象。
至此SqlSessionFactoryBuilder類的全部工作已經完成。

SqlSessionFactory階段

使用上步返回的DefaultSqlSessionFactory對象可以打開一個session會話(類似於在數據庫連接池中獲取到一個連接Connection

 public SqlSession openSession() {
    return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);
  }
   private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
    Transaction tx = null;
      final Environment environment = configuration.getEnvironment();
      final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
      tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
      final Executor executor = configuration.newExecutor(tx, execType);
      return new DefaultSqlSession(configuration, executor, autoCommit);
  }

和SqlSessionFactory一樣,SqlSession也是一個接口,它的默認實現是DefaultSqlSession,創建此對象時需要傳入全局配置對象,執行器,是否自動提交三個參數。

SqlSession階段

SqlSession中存在四個關鍵對象:Executor、StatementHandler、ParameterHandler、ResultHandler。
Executor代表調度器,負責使用其他Handler執行sql語句的。

public interface Executor {

  ResultHandler NO_RESULT_HANDLER = null;

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

  <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;

  <E> Cursor<E> queryCursor(MappedStatement ms, Object parameter, RowBounds rowBounds) throws SQLException;

  List<BatchResult> flushStatements() throws SQLException;

  void commit(boolean required) throws SQLException;

  void rollback(boolean required) throws SQLException;

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

  boolean isCached(MappedStatement ms, CacheKey key);

  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代表語句處理器,類似於PrepardStatement。

public interface StatementHandler {

  Statement prepare(Connection connection, Integer transactionTimeout)
      throws SQLException;

  void parameterize(Statement statement)
      throws SQLException;

  void batch(Statement statement)
      throws SQLException;

  int update(Statement statement)
      throws SQLException;

  <E> List<E> query(Statement statement, ResultHandler resultHandler)
      throws SQLException;

  <E> Cursor<E> queryCursor(Statement statement)
      throws SQLException;

  BoundSql getBoundSql();

  ParameterHandler getParameterHandler();

}

ParameterHandler代表參數處理器,負責處理參數到sql佔位符的轉化。

public interface ParameterHandler {

  Object getParameterObject();

  void setParameters(PreparedStatement ps)
      throws SQLException;
}

ResultHandler負責封裝返回的數據。

public interface ResultHandler<T> {

  void handleResult(ResultContext<? extends T> resultContext);

}

最後通過一張圖將所有的流程串起來
在這裏插入圖片描述
在sqlSession階段主要做的事情是獲取Mapper接口,調用Mapper中的方法,處理返回結果。

 DeptMapper mapper = sqlSession.getMapper(DeptMapper.class);
            HashMap<String, Integer> map = new HashMap<>();
            map.put("deptNo",1);
            Dept dept =  mapper.selectDept(map);
            System.out.println(dept);
            sqlSession.commit();

最重要的地方在於Mapper的獲取和使用上。

Mapper階段

mapper底層是使用動態代理技術創建對象的,對應的類爲MapperProxy,一個Mapper配置文件對應着三個類,分別爲MappedStatement、SqlSource、BoundSql。
MappedStatement代表着配置文件中insert、select、delete、update標籤和標籤裏設置的屬性值

public final class MappedStatement {

  private String resource;
  private Configuration configuration;
  private String id;
  private Integer fetchSize;
  private Integer timeout;
  private StatementType statementType;
  private ResultSetType resultSetType;
  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;
  }

sqlSource用來提供BoundSql對象,它是作爲MappedStatement的屬性存在的。

public interface SqlSource {

  BoundSql getBoundSql(Object parameterObject);

}

BoundSql 代表了一條sql以及對應的參數,它使用sql屬性表示寫在標籤裏的sql語句

public class BoundSql {

  private final String sql;
  private final List<ParameterMapping> parameterMappings;
  private final Object parameterObject;
  private final Map<String, Object> additionalParameters;
  private final MetaObject metaParameters;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章