1. 程式人生 > >Mybatis的SqlSession理解(二)

Mybatis的SqlSession理解(二)

.com lar aps elements ive name simple bin ret

Mybaits加載執行該xml配置

技術分享圖片

class SqlSessionFactoryBean implements FactoryBean<SqlSessionFactory>, InitializingBean

spring 在初始化 sqlsessionbean的時候通過createBean調用了在SqlSessionFactoryBean中實現了接口InitializingBean的afterPropertiesSet()方法在該方法中調用了buildSqlSessionFactory()開始創建SqlSessionFactory

buildSqlSessionFactory()方法完成以下功能

一:

a) 創建configuration

b) typeAliasesPackage

c) typeAliases TYPE_ALIASES將類型存放到此map裏面同b

d) plugins configuration添加插件

e) typeHandlersPackage

f) typeHandlers

g) xmlConfigBuilder.parse()將所有的配置從xml中讀取並放入到對應的變量裏面

h) mapperLocations

二:xmlMapperBuilder.parse()——> configurationElement

a) parameterMapElement(context.evalNodes("/mapper/parameterMap"));將mapper.xml中的prameterMap節點的數據添加到configuration.parameterMaps中

b) resultMapElements(context.evalNodes("/mapper/resultMap"));將mapper.xml中的resultMap節點的數據添加到configuration.incompleteResultMaps中

c) sqlElement(context.evalNodes("/mapper/sql"));

d) buildStatementFromContext(select|insert|update|delete);buildStatementFromContext:從mapper 中獲取sql語句,執行類型(增刪改查),parseStatementNode中addMappedStatement創建每個mapper對應的方法創建MappedStatement並添加到 configuration.mappedStatements.put(com.qb.mysql.dao.TRoleDao.getUserRoleByRid, MappedStatement)

最後返回了一個 DefaultSqlSessionFactory(config)

在調用SqlSessionTemplate進行dao層操作時,其會將工作委托給sqlSessionProxy屬性進行,而sqlSessionProxy在進行相關method調用時,用到了JDK動態代理機制,首先SqlSessionUtils.getSqlSession獲取sqlSession

 private class SqlSessionInterceptor implements InvocationHandler {
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//返回一個DefaultSqlsession
      SqlSession sqlSession = getSqlSession(
          SqlSessionTemplate.this.sqlSessionFactory,
          SqlSessionTemplate.this.executorType,
          SqlSessionTemplate.this.exceptionTranslator);
      try {
     //調用該類的MapperProxy的invoke方法
        Object result = method.invoke(sqlSession, args);
        if (!isSqlSessionTransactional(sqlSession, SqlSessionTemplate.this.sqlSessionFactory)) {
          // force commit even on non-dirty sessions because some databases require
          // a commit/rollback before calling close()
          sqlSession.commit(true);
        }
        return result;
      } catch (Throwable t) {
        Throwable unwrapped = unwrapThrowable(t);
        if (SqlSessionTemplate.this.exceptionTranslator != null && unwrapped instanceof PersistenceException) {
          // release the connection to avoid a deadlock if the translator is no loaded. See issue #22
          closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory);
          sqlSession = null;
          Throwable translated = SqlSessionTemplate.this.exceptionTranslator.translateExceptionIfPossible((PersistenceException) unwrapped);
          if (translated != null) {
            unwrapped = translated;
          }
        }
        throw unwrapped;
      } finally {
        if (sqlSession != null) {
          closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory);
        }
      }
    }
  }
在getSqlSession方法中創建事務,創建Executor,默認創建SimpleExecutor;InterceptorChain添加攔截器 InterceptorChain.pluginAll()

SqlSessionTemplate ->SqlSessionInterceptor->SqlSessionUtils. getSqlSession()->(defaultsqlsessionfactory)sessionFactory.openSession()->openSessionFromDataSource()

MapperProxy的invoke方法的方法
 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    if (Object.class.equals(method.getDeclaringClass())) {
      return method.invoke(this, args);
    }
    final MapperMethod mapperMethod = cachedMapperMethod(method);
//執行execute
    return mapperMethod.execute(sqlSession, args);
  }
//根據sql類型選擇對應的方法
public Object execute(SqlSession sqlSession, Object[] args) { Object result; if (SqlCommandType.INSERT == command.getType()) { Object param = method.convertArgsToSqlCommandParam(args); result = rowCountResult(sqlSession.insert(command.getName(), param)); } else if (SqlCommandType.UPDATE == command.getType()) { Object param = method.convertArgsToSqlCommandParam(args); result = rowCountResult(sqlSession.update(command.getName(), param)); } else if (SqlCommandType.DELETE == command.getType()) { Object param = method.convertArgsToSqlCommandParam(args); result = rowCountResult(sqlSession.delete(command.getName(), param)); } else if (SqlCommandType.SELECT == command.getType()) { if (method.returnsVoid() && method.hasResultHandler()) { executeWithResultHandler(sqlSession, args); result = null; } else if (method.returnsMany()) { result = executeForMany(sqlSession, args); } else if (method.returnsMap()) { result = executeForMap(sqlSession, args); } else { Object param = method.convertArgsToSqlCommandParam(args); result = sqlSession.selectOne(command.getName(), param); } } else { throw new BindingException("Unknown execution method for: " + command.getName()); } if (result == null && method.getReturnType().isPrimitive() && !method.returnsVoid()) { throw new BindingException("Mapper method ‘" + command.getName() + " attempted to return null from a method with a primitive return type (" + method.getReturnType() + ")."); } return result; }

SqlSessionTemplate 執行了創建sqlsession,openSqlsession,執行sql,closeSqlsession

Mybatis的SqlSession理解(二)