Mybatis精講(二)---生命週期

回顧

  • 上一章節咱們經過xml和代碼的方式實現了Mybatis環境的配置。代碼方式只是簡單介紹下。咱們也知道咱們大部分狀況使用的是xml方式的配置。在實際開發中咱們那樣開發顯然是不合理的。spring

  • 上章節提到的組件顯示不可能每次執行sql都要從新建立的。這樣性能上確定是過不去的。今天咱們就來簡單聊聊SqlSessionFactoryBuilder、SqlSessionFactory、SqlSession、Mapper這些組件的生命週期吧。sql

SqlSessionFactoryBuilder

  • 經過觀察分析這個類咱們就知道既然是Builder模式的類,那他的做用就是構建起(孵化器).換句話說這個類不是那麼的重要,由於他惟一的做用就是孵化SqlSessionFactory。在Spring與Mybatis整合的框架中,我相信Spring必定是在構建了SqlSessionFactory以後就將這個類進行回收了。由於後面就不須要了。這裏純屬我的猜測。
public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
  try {
    XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
    return build(parser.parse());
  } catch (Exception e) {
    throw ExceptionFactory.wrapException("Error building SqlSession.", e);
  } finally {
    ErrorContext.instance().reset();
    try {
      inputStream.close();
    } catch (IOException e) {
      // Intentionally ignore. Prefer previous error.
    }
  }
}
  • 上面就是咱們經過加載xml配置文件的源碼。咱們不難發現build核心是經過XMLConfigBuilder這個類去負責解析mybatis-config.xml配置文件並生成Configuration對象。

SqlSessionFactory

  • 看名字就知道是工廠模式。在這裏咱們能夠把他當作數據庫鏈接池。既然是工廠就確定得有產品。SqlSessionFactory的產物就是SqlSession。SqlSession是與數據庫的一次鏈接。管理數據庫的鏈接的天然就是鏈接池了。
  • Mybatis中使用的SqlSessionFactory是DefaultSqlSessionFactory 。 以鏈接池的角度看待咱們不難推斷出SqlSessionFactory應該是個單例 。SqlSessionFactory對應的是數據庫。一個數據庫原則上應該對應一個SqlSessionFactory來管理。這點在Spring中正好無縫鏈接。把SqlSessionFactory交由spring管理。spring默認是單例模式bean.

openSessionFromDataSource

  • SqlSessionFactory經過openSession方法獲取SqlSession.SQLSession實際上能夠看作是一次數據庫的鏈接。下面咱們經過源碼的方式去看看工廠是如何生產SqlSession的。
<!--定義數據庫信息,默認使用development數據庫構建環境-->
<environments default="development">
    <environment id="development">
        <!--jdbc事物管理-->
        <transactionManager type="JDBC"></transactionManager>
        <!--配置數據庫鏈接信息-->
        <dataSource type="POOLED">
            <property name="driver" value="${database.driver}"/>
            <property name="url" value="${database.url}"/>
            <property name="username" value="${database.username}"/>
            <property name="password" value="${database.password}"/>
        </dataSource>
    </environment>
</environments>
private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
  //定義一個事物對象
  Transaction tx = null;
  try {
    //經過配置對象獲取事先配置好的環境對象   這裏對應了xml中的environments標籤  。environments默認develop.因此是develop的environment
    final Environment environment = configuration.getEnvironment();
    //經過環境獲取事物。在environment裏配置了JDBC類型的事物==JdbcTransactionFactory;若是沒有配置則默認採用ManagedTransactionFactory
    final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
    //構建事物對象 , 實際就是屬性的賦值
    tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
    //獲取執行器 BatchExecutor、ReuseExecutor、SimpleExecutor , 選擇SimpleExecutor
    //由於默認有緩存,這裏會用CachingExecutor包裹原始Executor , 以後會加載各類插件
    final Executor executor = configuration.newExecutor(tx, execType);
    //返回DefaultSqlSession。寫死
    return new DefaultSqlSession(configuration, executor, autoCommit);
  } catch (Exception e) {
    closeTransaction(tx); // may have fetched a connection so lets call close()
    throw ExceptionFactory.wrapException("Error opening session.  Cause: " + e, e);
  } finally {
    ErrorContext.instance().reset();
  }
}

Executor

  • Mybatis的數據庫執行器。Mybatis提供了一共四中Executor.這裏嚴格意義上應該說是三種 BatchExecutor、ReuseExecutor、SimpleExecutor。還有一個CachingExecutor。這裏爲何不把他算上了。由於這個是一個全局的開關。在settings標籤的cacheEnabled設置的。說道這個標籤你們都知道這個就是二級緩存的開關。因此這裏CachingExecutor就不作介紹了。
  • SimpleExecutor是一種常規執行器,每次執行都會建立一個statement,用完後關閉。
  • ReuseExecutor是可重用執行器,將statement存入map中,操做map中的statement而不會重複建立statement。
  • BatchExecutor是批處理型執行器,doUpdate預處理存儲過程或批處理操做,doQuery提交併執行過程。
  • 關於Executor的選取也是在settings標籤控制的。defaultExecutorType。 默認是simple

SqlSession

  • 每一個線程都有一個屬於本身的Sqlsession對象。這裏咱們當作是一次Connection。他的生命週期應該是一次完成的事物處理過程。他是一個線程不安全的對象。在多線程操做的時候咱們須要注意事物的隔離級別。咱們操做時須要注意的是每次處理玩須要將他關閉。不然會形成資源浪費。在Mybaits中已經經過finnally把咱們將他釋放了。

Mapper

  • Mapper是一個接口,咱們能夠將xml當作他的一個實現類。這裏的實現類虛化。經過Java代碼的調用實際將xml對應的sql發送給數據庫並獲取數據結果。
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
  final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);
  if (mapperProxyFactory == null) {
    throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
  }
  try {
    return mapperProxyFactory.newInstance(sqlSession);
  } catch (Exception e) {
    throw new BindingException("Error getting mapper instance. Cause: " + e, e);
  }
}
  • 經過上述代碼咱們可以發現。在獲取Mapper的時候先經過類型看是否被註冊了。而後根據類別獲取代理實例。

總結

  • 關於生命週期其實沒什麼重點。這一章節也比較簡單。咱們只須要知道咱們最終須要的Mapper。而後是如何從配置到獲取Mapper.這過程當中哪些是全局的。哪些又適合作成複用的。

加入戰隊數據庫

# 加入戰隊

微信公衆號

微信公衆號

相關文章
相關標籤/搜索