MyBatis的Sql执行过程源码解读

来源:互联网 发布:卫生部 疾病数据 编辑:程序博客网 时间:2024/04/20 21:23

1.先获得SqlSessionFactory

         通过SqlSessionFactoryBuilder去读取mybatis的配置文件,然后build一个DefaultSqlSessionFactory。

/**   * 一系列的构造方法最终都会调用本方法(配置文件为Reader时会调用本方法,还有一个InputStream方法与此对应)   * @param reader   * @param environment   * @param properties   * @return   */  public SqlSessionFactory build(Reader reader, String environment, Properties properties) {    try {      //通过XMLConfigBuilder解析配置文件,解析的配置相关信息都会封装为一个Configuration对象      XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties);      //这儿创建DefaultSessionFactory对象      return build(parser.parse());    } catch (Exception e) {      throw ExceptionFactory.wrapException("Error building SqlSession.", e);    } finally {      ErrorContext.instance().reset();      try {        reader.close();      } catch (IOException e) {        // Intentionally ignore. Prefer previous error.      }    }  }  public SqlSessionFactory build(Configuration config) {    return new DefaultSqlSessionFactory(config);  }


2.通过SqlSessionFactory去获取SqlSession对象

  public SqlSession openSession()   {    return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);  }
  private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit)   {    Transaction tx = null;    try     {      //通过Configuration对象去获取相关的配置信息,Environment对象包含了数据源和事务的配置      final Environment environment = configuration.getEnvironment();      final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);      tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);      //实际上就是Executor来执行sql语句,executor是对于Statement的封装      final Executor executor = configuration.newExecutor(tx, execType, autoCommit);      //创建DefaultSqlSession对象      return new DefaultSqlSession(configuration, executor);    }    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();    }  }
                      这样就获得了SqlSession对象


3.通过SqlSession获得Mapper

  public <T> T getMapper(Class<T> type)   {    return configuration.<T>getMapper(type, this);  }
            这里通过Configuration的getMapper方法来获得

  public <T> T getMapper(Class<T> type, SqlSession sqlSession)   {    return mapperRegistry.getMapper(type, sqlSession);  }
  protected MapperRegistry mapperRegistry = new MapperRegistry(this);

     继续看MapperRegistry的getMapper方法

  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);   //此处使用反射,生成一个MapperProxyFactory对象    }    catch (Exception e)     {      throw new BindingException("Error getting mapper instance. Cause: " + e, e);    }  }
  private final Map<Class<?>, MapperProxyFactory<?>> knownMappers = new HashMap<Class<?>, MapperProxyFactory<?>>();<span style="font-family: Arial, Helvetica, sans-serif; font-size: 12px; background-color: rgb(255, 255, 255);">            </span>

         knownMappers在读取配置文件的时候,已经将mapper信息放入其中了。

        继续看MapperProxyFactory的newInstance方法:

  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);  }
        MapperProxy就是一个代理类,使用的是jdk的动态代理

  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);    return mapperMethod.execute(sqlSession, args);  }
       这里的invoke方法可以明确看出使用的是jdk的动态代理

      这样的话就会返回一个mapper的代理类,每次执行的时候,回交给MapperMethod类的execute方法

  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;}
               可以看出,也就是判断一下CURD的类型,然后实际调用的还是SqlSession 的方法,在这里以selectList为例

  public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {    try {      MappedStatement ms = configuration.getMappedStatement(statement);      List<E> result = executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);      return result;    } catch (Exception e) {      throw ExceptionFactory.wrapException("Error querying database.  Cause: " + e, e);    } finally {      ErrorContext.instance().reset();    }  }
          继续查找Executor的query方法,在这里使用BaseExecutor的

  public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException  {    BoundSql boundSql = ms.getBoundSql(parameter);    CacheKey key = createCacheKey(ms, parameter, rowBounds, boundSql);    return query(ms, parameter, rowBounds, resultHandler, key, boundSql); }
         继续查找到SimpleExecutor的doQuery,可以看到

  public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException     {    Statement stmt = null;    try     {      Configuration configuration = ms.getConfiguration();      StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, rowBounds, resultHandler, boundSql);      stmt = prepareStatement(handler, ms.getStatementLog());      return handler.<E>query(stmt, resultHandler);    }    finally     {      closeStatement(stmt);    }  }
  private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException   {    Statement stmt;    Connection connection = getConnection(statementLog);    stmt = handler.prepare(connection);    handler.parameterize(stmt);    return stmt;  }
      可以看出实际上也就好似调用的jdbc


0 0
原创粉丝点击