MyBatis3.3.0文檔學習總結(三續) --sqlSession深入源碼

工廠接口(sqlSessionFactory)如何創建sqlsession會話接口.

   public static SqlSession openSession() {  
            return getSqlSessionFactory().openSession();  
        }  

openSession() 方法調用package org.apache.ibatis.session.defaults ,DefaultSqlSessionFactory類的openSession方法。

  public SqlSession openSession() {
    return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);
  }

調用同一個類下的openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);方法。從這我們就可以猜到這裏設定了Session的SQL執行器的類型、事務類型和是否自動提交。而這些設置信息都是由配置文件configuration決定的。這樣我們就知道了配置信息是如何決定了sqlSession的功能。

  private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
    Transaction tx = null;
    try {
      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);*
    } 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();
    }
  }

返回了DefaultSqlSession(configuration,executor,autoCommit)的 實例,這是DefaultSqlSession類的構造方法。

補充:package org.apache.ibatis.session;下ExecutorType.class源碼。

public enum ExecutorType {
  SIMPLE, REUSE, BATCH
}

package org.apache.ibatis.session; 下的Configuration.class類,設置defaultExecutorType的值是“SIMPLE”

protected ExecutorType defaultExecutorType = ExecutorType.SIMPLE;

我們已經拿到了一個SqlSession的實例,也就是說我們已經明白了1.的執行步驟,現在我們來看2.3.的執行過程。

 1.     SqlSession sqlSession = MyBatisSqlSessionFactory.openSession();   
 2.  StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);  
 3.  return studentMapper.findAllStudents();  

sqlsession.getMapper(StudentMapper.class)方法,調用了package org.apache.ibatis.session.defaults;下的DefaultSqlSession的getMapper(xxx.class)方法。源碼如下:

  @Override
  public <T> T getMapper(Class<T> type) {
    return configuration.<T>getMapper(type, this);
  }

調用了configuration實例的

  public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
    return mapperRegistry.getMapper(type, sqlSession);
  }

調用了package org.apache.ibatis.binding;下的mapperRegistry實例的:

  @SuppressWarnings("unchecked")
  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);
    }
  }

通過knownMappers獲取一個MapperProxyFactory。knowMappers代碼如下:

private final Map<Class<?>, MapperProxyFactory<?>> knownMappers = new HashMap<Class<?>, MapperProxyFactory<?>>();

然後newInstance,調用package org.apache.ibatis.binding;下的MapperProxyFactory 類的newInstance(SqlSession sqlSession)方法。再調用此類下的newInstance(MapperProxy mapperProxy)方法,通過動態代理,我們就可以使用接口了。 (這個我也不懂。。。),

 private final Class<T> mapperInterface;
 @SuppressWarnings("unchecked")
  protected T newInstance(MapperProxy<T> mapperProxy) {
    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);
  }

得到了mapper實例。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章