初始化 + 执行流程的源码解析就按照我们测试类的编写来看,从Resources.getResourceAsStream()开始。

加载配置文件

  1. // Resources就是一个工具类,将配置文件转化为字节输入流,这个步骤不涉及任何解析操作
  2. InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapperConfig.xml");
  3. // 执行的源码
  4. public static InputStream getResourceAsStream(String resource) throws IOException {
  5. return getResourceAsStream(null, resource);
  6. }
  7. /**
  8. * Returns a resource on the classpath as a Stream object
  9. *
  10. * @param loader The classloader used to fetch the resource
  11. * @param resource The resource to find
  12. * @return The resource
  13. * @throws java.io.IOException If the resource cannot be found or read
  14. */
  15. public static InputStream getResourceAsStream(ClassLoader loader, String resource) throws IOException {
  16. InputStream in = classLoaderWrapper.getResourceAsStream(resource, loader);
  17. if (in == null) {
  18. throw new IOException("Could not find resource " + resource);
  19. }
  20. return in;
  21. }

解析配置文件

  1. // 执行代码如下,做的操作就是解析配置文件,功能有如下两点,使用了构建者模式
  2. // 1. 封装Configuration配置文件,内部有各种配置文件的设置以及存放MappedStatement的map
  3. // 2. 创建DefaultSqlSessionFactory
  4. private SqlSessionFactory build = new SqlSessionFactoryBuilder().build(resourceAsStream);
  5. // 源码说明,主要方法如下
  6. public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
  7. try {
  8. // 仅仅XPathParser解析
  9. XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
  10. // parse方法是关键,重中之重,parse方法封装configuration对对象,build方法根据configuration来创建工厂
  11. return build(parser.parse());
  12. } catch (Exception e) {
  13. throw ExceptionFactory.wrapException("Error building SqlSession.", e);
  14. } finally {
  15. ErrorContext.instance().reset();
  16. try {
  17. inputStream.close();
  18. } catch (IOException e) {
  19. // Intentionally ignore. Prefer previous error.
  20. }
  21. }
  22. }
  23. public Configuration parse() {
  24. if (parsed) {
  25. throw new BuilderException("Each XMLConfigBuilder can only be used once.");
  26. }
  27. parsed = true;
  28. parseConfiguration(parser.evalNode("/configuration"));
  29. return configuration;
  30. }
  31. private void parseConfiguration(XNode root) {
  32. try {
  33. // 解析各种标签
  34. propertiesElement(root.evalNode("properties"));
  35. Properties settings = settingsAsProperties(root.evalNode("settings"));
  36. loadCustomVfs(settings);
  37. loadCustomLogImpl(settings);
  38. typeAliasesElement(root.evalNode("typeAliases"));
  39. pluginElement(root.evalNode("plugins"));
  40. objectFactoryElement(root.evalNode("objectFactory"));
  41. objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
  42. reflectorFactoryElement(root.evalNode("reflectorFactory"));
  43. settingsElement(settings);
  44. // read it after objectFactory and objectWrapperFactory issue #631
  45. environmentsElement(root.evalNode("environments"));
  46. databaseIdProviderElement(root.evalNode("databaseIdProvider"));
  47. typeHandlerElement(root.evalNode("typeHandlers"));
  48. mapperElement(root.evalNode("mappers"));
  49. } catch (Exception e) {
  50. throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
  51. }
  52. }

创建会话对象SqlSession

  1. // 功能也有两点
  2. // 1. 创建会话对象
  3. // 2. 创建执行器
  4. private SqlSession sqlSession = build.openSession();
  5. // 第一个参数值执行器的类型,根据实现有三种,默认是 SIMPLE,第二个参数是事务隔离级别,第三个参数是事务是否自动提交
  6. private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
  7. Transaction tx = null;
  8. try {
  9. final Environment environment = configuration.getEnvironment();
  10. final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
  11. tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
  12. final Executor executor = configuration.newExecutor(tx, execType);
  13. return new DefaultSqlSession(configuration, executor, autoCommit);
  14. } catch (Exception e) {
  15. closeTransaction(tx); // may have fetched a connection so lets call close()
  16. throw ExceptionFactory.wrapException("Error opening session. Cause: " + e, e);
  17. } finally {
  18. ErrorContext.instance().reset();
  19. }
  20. }

调用方法

  1. // 执行sql,返回结果
  2. List<Object> objects = sqlSession.selectList("statement.id");
  3. // 最后方法如下
  4. @Override
  5. public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
  6. try {
  7. // 根据参数statementId来获取MappedStatement
  8. MappedStatement ms = configuration.getMappedStatement(statement);
  9. // 进行方法的执行
  10. return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);
  11. } catch (Exception e) {
  12. throw ExceptionFactory.wrapException("Error querying database. Cause: " + e, e);
  13. } finally {
  14. ErrorContext.instance().reset();
  15. }
  16. }

执行器的查看

主要就是看上面的query方法:

  1. @Override
  2. public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
  3. BoundSql boundSql = ms.getBoundSql(parameter);
  4. CacheKey key = createCacheKey(ms, parameter, rowBounds, boundSql);
  5. return query(ms, parameter, rowBounds, resultHandler, key, boundSql);
  6. }
  7. public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
  8. ErrorContext.instance().resource(ms.getResource()).activity("executing a query").object(ms.getId());
  9. if (closed) {
  10. throw new ExecutorException("Executor was closed.");
  11. }
  12. if (queryStack == 0 && ms.isFlushCacheRequired()) {
  13. clearLocalCache();
  14. }
  15. List<E> list;
  16. try {
  17. queryStack++;
  18. list = resultHandler == null ? (List<E>) localCache.getObject(key) : null;
  19. if (list != null) {
  20. handleLocallyCachedOutputParameters(ms, key, parameter, boundSql);
  21. } else {
  22. list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);
  23. }
  24. } finally {
  25. queryStack--;
  26. }
  27. if (queryStack == 0) {
  28. for (DeferredLoad deferredLoad : deferredLoads) {
  29. deferredLoad.load();
  30. }
  31. // issue #601
  32. deferredLoads.clear();
  33. if (configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) {
  34. // issue #482
  35. clearLocalCache();
  36. }
  37. }
  38. return list;
  39. }
  40. private <E> List<E> queryFromDatabase(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
  41. List<E> list;
  42. localCache.putObject(key, EXECUTION_PLACEHOLDER);
  43. try {
  44. list = doQuery(ms, parameter, rowBounds, resultHandler, boundSql);
  45. } finally {
  46. localCache.removeObject(key);
  47. }
  48. localCache.putObject(key, list);
  49. if (ms.getStatementType() == StatementType.CALLABLE) {
  50. localOutputParameterCache.putObject(key, parameter);
  51. }
  52. return list;
  53. }
  54. @Override
  55. public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
  56. Statement stmt = null;
  57. try {
  58. // 获取配置信息
  59. Configuration configuration = ms.getConfiguration();
  60. // 创建 StatementHandler 对象,作用有两个
  61. // 1. 设置参数 ParameterHandler
  62. // 2. 处理返回结果集 ResultSetHandler
  63. StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
  64. // 预处理sql,创建statement对象,完成参数的设置,并且其中有TypeHandler的使用
  65. stmt = prepareStatement(handler, ms.getStatementLog());
  66. // 数据查询处理
  67. return handler.query(stmt, resultHandler);
  68. } finally {
  69. closeStatement(stmt);
  70. }
  71. }
  72. @Override
  73. public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
  74. String sql = boundSql.getSql();
  75. statement.execute(sql);
  76. return resultSetHandler.handleResultSets(statement);
  77. }

StatementHandler的流程

  1. // 首先看设置参数
  2. private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
  3. Statement stmt;
  4. Connection connection = getConnection(statementLog);
  5. stmt = handler.prepare(connection, transaction.getTimeout());
  6. handler.parameterize(stmt);
  7. return stmt;
  8. }
  9. @Override
  10. public void parameterize(Statement statement) throws SQLException {
  11. // 交给了ParameterHandler去进行参数设置
  12. parameterHandler.setParameters((PreparedStatement) statement);
  13. }
  14. public void setParameters(PreparedStatement ps) {
  15. ErrorContext.instance().activity("setting parameters").object(mappedStatement.getParameterMap().getId());
  16. List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
  17. if (parameterMappings != null) {
  18. for (int i = 0; i < parameterMappings.size(); i++) {
  19. ParameterMapping parameterMapping = parameterMappings.get(i);
  20. if (parameterMapping.getMode() != ParameterMode.OUT) {
  21. Object value;
  22. // 获取字段名称以及字段值
  23. String propertyName = parameterMapping.getProperty();
  24. if (boundSql.hasAdditionalParameter(propertyName)) { // issue #448 ask first for additional params
  25. value = boundSql.getAdditionalParameter(propertyName);
  26. } else if (parameterObject == null) {
  27. value = null;
  28. } else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
  29. value = parameterObject;
  30. } else {
  31. MetaObject metaObject = configuration.newMetaObject(parameterObject);
  32. value = metaObject.getValue(propertyName);
  33. }
  34. // jdbc与java type映射
  35. // 每⼀个 Mapping都有⼀个 TypeHandler,根据 TypeHandler 来对preparedStatement 进 ⾏设置参数
  36. TypeHandler typeHandler = parameterMapping.getTypeHandler();
  37. JdbcType jdbcType = parameterMapping.getJdbcType();
  38. if (value == null && jdbcType == null) {
  39. jdbcType = configuration.getJdbcTypeForNull();
  40. }
  41. try {
  42. typeHandler.setParameter(ps, i + 1, value, jdbcType);
  43. } catch (TypeException | SQLException e) {
  44. throw new TypeException("Could not set parameters for mapping: " + parameterMapping + ". Cause: " + e, e);
  45. }
  46. }
  47. }
  48. }
  49. }
  50. // 执行方法以及结果集的处理
  51. @Override
  52. public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
  53. PreparedStatement ps = (PreparedStatement) statement;
  54. ps.execute();
  55. // 教给了 ResultSetHandler进行处理
  56. return resultSetHandler.handleResultSets(ps);
  57. }
  58. public List<Object> handleResultSets(Statement stmt) throws SQLException {
  59. ErrorContext.instance().activity("handling results").object(mappedStatement.getId());
  60. final List<Object> multipleResults = new ArrayList<>();
  61. int resultSetCount = 0;
  62. ResultSetWrapper rsw = getFirstResultSet(stmt);
  63. List<ResultMap> resultMaps = mappedStatement.getResultMaps();
  64. int resultMapCount = resultMaps.size();
  65. validateResultMapsCount(rsw, resultMapCount);
  66. // while结果集处理
  67. while (rsw != null && resultMapCount > resultSetCount) {
  68. ResultMap resultMap = resultMaps.get(resultSetCount);
  69. handleResultSet(rsw, resultMap, multipleResults, null);
  70. rsw = getNextResultSet(stmt);
  71. cleanUpAfterHandlingResultSet();
  72. resultSetCount++;
  73. }
  74. String[] resultSets = mappedStatement.getResultSets();
  75. if (resultSets != null) {
  76. while (rsw != null && resultSetCount < resultSets.length) {
  77. ResultMapping parentMapping = nextResultMaps.get(resultSets[resultSetCount]);
  78. if (parentMapping != null) {
  79. String nestedResultMapId = parentMapping.getNestedResultMapId();
  80. ResultMap resultMap = configuration.getResultMap(nestedResultMapId);
  81. handleResultSet(rsw, resultMap, null, parentMapping);
  82. }
  83. rsw = getNextResultSet(stmt);
  84. cleanUpAfterHandlingResultSet();
  85. resultSetCount++;
  86. }
  87. }
  88. return collapseSingleResultList(multipleResults);
  89. }
  90. private List<Object> collapseSingleResultList(List<Object> multipleResults) {
  91. return multipleResults.size() == 1 ? (List<Object>) multipleResults.get(0) : multipleResults;
  92. }