ibatis源码分析—运行流程解析(二)

二、具体流程

1、流程入口。一般都是在XXXDAOImpl中调用了getSqlMapClientTmplate().queryXXXX()方法。

2、方法入口。getSqlMapClientTmplate类的execute()方法为具体执行方法,参数为一个匿名内部类,用于回调doInSqlMapClient()方法。


public <T> T execute(SqlMapClientCallback<T> action) throws DataAccessException {
		Assert.notNull(action, "Callback object must not be null");
		Assert.notNull(this.sqlMapClient, "No SqlMapClient specified");
		//创建SqlMapSessionImpl对象,这个对象用来维持数据交互的环境。
		SqlMapSession session = this.sqlMapClient.openSession();
		if (logger.isDebugEnabled()) {
			logger.debug("Opened SqlMapSession [" + session + "] for iBATIS operation");
		}
		Connection ibatisCon = null

		try {
			Connection springCon = null;
			//获取数据源
			DataSource dataSource = getDataSource();
			boolean transactionAware = (dataSource instanceof TransactionAwareDataSourceProxy);

			// Obtain JDBC Connection to operate on...
			try {
				ibatisCon = session.getCurrentConnection();
				if (ibatisCon == null) {
					springCon = (transactionAware ?
							dataSource.getConnection() : DataSourceUtils.doGetConnection(dataSource));
					//设置数据源		
					session.setUserConnection(springCon);
					if (logger.isDebugEnabled()) {
						logger.debug("Obtained JDBC Connection [" + springCon + "] for iBATIS operation");
					}
				}
				else {
					if (logger.isDebugEnabled()) {
						logger.debug("Reusing JDBC Connection [" + ibatisCon + "] for iBATIS operation");
					}
				}
			}
			catch (SQLException ex) {
				throw new CannotGetJdbcConnectionException("Could not get JDBC Connection", ex);
			}

			// Execute given callback...
			try {
                        	//进行回调。
				return action.doInSqlMapClient(session);
			}
			catch (SQLException ex) {
				throw getExceptionTranslator().translate("SqlMapClient operation", null, ex);
			}
			finally {
				try {
					if (springCon != null) {
						if (transactionAware) {
							springCon.close();
						}
						else {
							DataSourceUtils.doReleaseConnection(springCon, dataSource);
						}
					}
				}
				catch (Throwable ex) {
					logger.debug("Could not close JDBC Connection", ex);
				}
			}

			// Processing finished - potentially session still to be closed.
		}
		finally {
			//关闭连接
			if (ibatisCon == null) {
				session.close();
			}
		}
	}




3、回调方法。

public Object queryForObject(String id, Object paramObject, Object resultObject) throws SQLException {
    //调用SqlMapExecutorDelegate这个代理类进行操作
    return delegate.queryForObject(session, id, paramObject, resultObject);
}


 

4、设置获取statement和初始化request

public Object queryForObject(SessionScope session, String id, Object paramObject, Object resultObject) throws SQLException {
    Object object = null;
    //根据上送的id,在mappedStatements这个map中获取当前的statement
    MappedStatement ms = getMappedStatement(id);
    //获取当前的事物
    Transaction trans = getTransaction(session);
    boolean autoStart = trans == null;

    try {
      trans = autoStartTransaction(session, autoStart, trans);
      //从requestpool中取出一个request,把session数据都放入到request中,以后的执行环境为request
      RequestScope request = popRequest(session, ms);
      try {
        //
        object = ms.executeQueryForObject(request, trans, paramObject, resultObject);
      } finally {
        pushRequest(request);
      }

      autoCommitTransaction(session, autoStart);
    } finally {
      autoEndTransaction(session, autoStart);
    }

    return object;
  }


</pre><pre name="code" class="java">protected RequestScope popRequest(SessionScope session, MappedStatement mappedStatement) {
    //requestpool中获取request
    RequestScope request = (RequestScope) requestPool.pop();
    session.incrementRequestStackDepth();
    request.setSession(session);
    //初始化request
    mappedStatement.initRequest(request);
    return request;
  }

</pre><p style="margin-top:0px; margin-bottom:0px; font-size:14px; font-family:Monaco"></p><pre name="code" class="java">
public void initRequest(RequestScope request) {
    //将statement、parameterMap、resultMap、Sql对象都放入到request中
    request.setStatement(this);
    request.setParameterMap(parameterMap);
    request.setResultMap(resultMap);
    request.setSql(sql);
  }



5、交互的数据以及环境准备好后,就进行数据交互

public Object executeQueryForObject(RequestScope request, Transaction trans, Object parameterObject, Object resultObject)
      throws SQLException {
    try {
      Object object = null;

      DefaultRowHandler rowHandler = new DefaultRowHandler();
      //查询方法
      executeQueryWithCallback(request, trans.getConnection(), parameterObject, resultObject, rowHandler, SqlExecutor.NO_SKIPPED_RESULTS, SqlExecutor.NO_MAXIMUM_RESULTS);
      List list = rowHandler.getList();
      //对结果的处理executeQueryForObject为查询单个对象。
      if (list.size() > 1) {
        throw new SQLException("Error: executeQueryForObject returned too many results.");
      } else if (list.size() > 0) {
        object = list.get(0);
      }

      return object;
    } catch (TransactionException e) {
      throw new NestedSQLException("Error getting Connection from Transaction.  Cause: " + e, e);
    }
  }


protected void executeQueryWithCallback(RequestScope request, Connection conn, Object parameterObject, Object resultObject, RowHandler rowHandler, int skipResults, int maxResults)
      throws SQLException {
    ErrorContext errorContext = request.getErrorContext();
    errorContext.setActivity("preparing the mapped statement for execution");
    errorContext.setObjectId(this.getId());
    errorContext.setResource(this.getResource());

    try {
      parameterObject = validateParameter(parameterObject);
      //获取sql对象,该对象对象可能有3种实力,dynamicsql,simpledynamicsql,staticsql。
      Sql sql = getSql();
      //获取ParameterMap,如果是simpledynamicsql,staticsql则直接从request中获取,如果是dynamicsql则需要重新处理
      errorContext.setMoreInfo("Check the parameter map.");
      ParameterMap parameterMap = sql.getParameterMap(request, parameterObject);
      //获取ResultMap,都从request中获取
      errorContext.setMoreInfo("Check the result map.");
      ResultMap resultMap = sql.getResultMap(request, parameterObject);

      request.setResultMap(resultMap);
      request.setParameterMap(parameterMap);
      //获取参数值。通过dataexchange对象获取,该对象有多种实例,具体是哪种取决于parameterClass,请看DataExchangeFactory类
      errorContext.setMoreInfo("Check the parameter map.");
      Object[] parameters = parameterMap.getParameterObjectValues(request, parameterObject);

      errorContext.setMoreInfo("Check the SQL statement.");
      //获取当前的sql
      String sqlString = sql.getSql(request, parameterObject);

      errorContext.setActivity("executing mapped statement");
      errorContext.setMoreInfo("Check the SQL statement or the result map.");
      RowHandlerCallback callback = new RowHandlerCallback(resultMap, resultObject, rowHandler);
      //调用SqlExecutor的executeQuery方法()进行查询。
      sqlExecuteQuery(request, conn, sqlString, parameters, skipResults, maxResults, callback);
      errorContext.setMoreInfo("Check the output parameters.");
      if (parameterObject != null) {
        postProcessParameterObject(request, parameterObject, parameters);
      }

      errorContext.reset();
      sql.cleanup(request);
      notifyListeners();
    } catch (SQLException e) {
      errorContext.setCause(e);
      throw new NestedSQLException(errorContext.toString(), e.getSQLState(), e.getErrorCode(), e);
    } catch (Exception e) {
      errorContext.setCause(e);
      throw new NestedSQLException(errorContext.toString(), e);
    }
  }


</pre><pre name="code" class="java">public void executeQuery(RequestScope request, Connection conn, String sql, Object[] parameters, int skipResults, int maxResults, RowHandlerCallback callback) throws SQLException {
    ErrorContext errorContext = request.getErrorContext();
    errorContext.setActivity("executing query");
    errorContext.setObjectId(sql);
    PreparedStatement ps = null;
    ResultSet rs = null;
    setupResultObjectFactory(request);
    try {
      errorContext.setMoreInfo("Check the SQL Statement (preparation failed).");
      Integer rsType = request.getStatement().getResultSetType();
      //初始化ps
      if (rsType != null) {
        ps = prepareStatement(request.getSession(), conn, sql, rsType);
      } else {
        ps = prepareStatement(request.getSession(), conn, sql);
      }
      setStatementTimeout(request.getStatement(), ps);
      Integer fetchSize = request.getStatement().getFetchSize();
      if (fetchSize != null) {
        ps.setFetchSize(fetchSize.intValue());
      }
      errorContext.setMoreInfo("Check the parameters (set parameters failed).");
      request.getParameterMap().setParameters(request, ps, parameters);
      errorContext.setMoreInfo("Check the statement (query failed).");
      //执行sql,这里只是个代理方法。
      ps.execute();
      errorContext.setMoreInfo("Check the results (failed to retrieve results).");

      //callback为回调参数,将result放入到callback中
      rs = handleMultipleResults(ps, request, skipResults, maxResults, callback);
      //
    } finally {
      try {
        closeResultSet(rs);
      } finally {
        closeStatement(request.getSession(), ps);
      }
    }

  }

 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
无法解析符号 'ibatis'通常是由于缺少相关依赖库或配置文件引起的。请确保您已经正确地配置了iBatis,并且所有必需的依赖项都已经添加到您的项目中。如果您使用的是Maven,则可以尝试更新您的依赖项并重新构建项目。如果问题仍然存在,请检查您的配置文件是否正确,并确保您的代码中没有任何拼写错误或语法错误。 以下是一些可能有用的步骤: 1.检查您的项目是否正确地包含了iBatis的依赖项。您可以在Maven中使用以下依赖项: ```xml <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.6</version> </dependency> ``` 2.检查您的配置文件是否正确。您需要确保您的配置文件中包含正确的命名空间和标签,并且所有属性都已正确设置。以下是一个示例配置文件: ```xml <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <environments default="development"> <environment id="development"> <transactionManager type="JDBC" /> <dataSource type="POOLED"> <property name="driver" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://localhost:3306/mybatis" /> <property name="username" value="root" /> <property name="password" value="password" /> </dataSource> </environment> </environments> <mappers> <mapper resource="com/example/mappers/UserMapper.xml" /> </mappers> </configuration> ``` 3.检查您的代码是否正确。请确保您的代码中没有任何拼写错误或语法错误,并且您已经正确地导入了所有必需的类和包。以下是一个示例代码: ```java import org.apache.ibatis.session.SqlSession; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.session.SqlSessionFactoryBuilder; public class MyBatisExample { public static void main(String[] args) { String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); SqlSession session = sqlSessionFactory.openSession(); try { UserMapper mapper = session.getMapper(UserMapper.class); User user = mapper.getUserById(1); System.out.println(user); } finally { session.close(); } } } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值