ibatis源码学习(一)整体设计和核心流程
本文主要从ibatis框架的基本代码骨架进行切入,理解ibatis框架的整体设计思路,各组件的实现细节将在后文进行分析。
背景
介绍ibatis实现之前,先来看一段jdbc代码:
Class.forName("com.mysql.jdbc.Driver");String url = "jdbc:mysql://localhost:3306/learnworld";Connection con = DriverManager.getConnection(url, "root","learnworld");String sql = "select * from test";PreparedStatement ps = con.prepareStatement(sql);ResultSet rs = ps.executeQuery();while(rs.next()){System.out.println("id=" + rs.getInt(1)+". score=" + rs.getInt(2));}
<bean id="sqlMapClient" ref="dataSource" /> <property name="configLocation" value="classpath/sqlmap/sqlmap-ibatis.xml" /> </bean>
public void afterPropertiesSet() throws Exception {...this.sqlMapClient = buildSqlMapClient(this.configLocations, this.mappingLocations, this.sqlMapClientProperties); //初始化核心方法,构建sqlMapClient对象...}
protected SqlMapClient buildSqlMapClient(Resource[] configLocations, Resource[] mappingLocations, Properties properties)throws IOException { ...SqlMapClient client = null;SqlMapConfigParser configParser = new SqlMapConfigParser();for (int i = 0; i < configLocations.length; i++) {InputStream is = configLocations[i].getInputStream();try {client = configParser.parse(is, properties); //通过SqlMapConfigParser解析配置文件,生成SQLMapClientImpl对象}catch (RuntimeException ex) {throw new NestedIOException("Failed to parse config resource: " + configLocations[i], ex.getCause());}}...return client;}
public Object queryForObject(final String statementName, final Object parameterObject)throws DataAccessException {return execute(new SqlMapClientCallback() {public Object doInSqlMapClient(SqlMapExecutor executor) throws SQLException {return executor.queryForObject(statementName, parameterObject);}});}
public Object execute(SqlMapClientCallback action) throws DataAccessException { ...SqlMapSession session = this.sqlMapClient.openSession(); //获取session信息Connection ibatisCon = null; //获取Connectiontry {Connection springCon = null;DataSource dataSource = getDataSource();boolean transactionAware = (dataSource instanceof TransactionAwareDataSourceProxy);try {ibatisCon = session.getCurrentConnection();if (ibatisCon == null) {springCon = (transactionAware ?dataSource.getConnection() : DataSourceUtils.doGetConnection(dataSource));session.setUserConnection(springCon);...}}...// Execute given callback...try {return action.doInSqlMapClient(session); //执行SQL}...finally { // 关闭Connectiontry {if (springCon != null) {if (transactionAware) {springCon.close(); }else {DataSourceUtils.doReleaseConnection(springCon, dataSource);}}}if (ibatisCon == null) {session.close(); //关闭session}}
public Object queryForObject(final String statementName, final Object parameterObject)throws DataAccessException {return execute(new SqlMapClientCallback() { //这里的SqlMapExecutor对象类型为SqlMapSessionImplpublic Object doInSqlMapClient(SqlMapExecutor executor) throws SQLException {return executor.queryForObject(statementName, parameterObject);}});}
public Object queryForObject(String id, Object paramObject) throws SQLException { return delegate.queryForObject(session, id, paramObject); }
public Object queryForObject(SessionScope session, String id, Object paramObject, Object resultObject) throws SQLException { Object object = null; MappedStatement ms = getMappedStatement(id); //MappedStatement对象集是上文中提及的初始化方法SqlMapClientFactoryBean.afterPropertiesSet()中,由配置文件构建而成 Transaction trans = getTransaction(session); // 用于事务执行 boolean autoStart = trans == null; try { trans = autoStartTransaction(session, autoStart, trans); RequestScope request = popRequest(session, ms); // 从RequestScope池中获取该次sql执行中的上下文环境RequestScope try { object = ms.executeQueryForObject(request, trans, paramObject, resultObject); // 执行sql } finally { pushRequest(request); //归还RequestScope } autoCommitTransaction(session, autoStart); } finally { autoEndTransaction(session, autoStart); } return object; }
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); //执行sql语句 //结果处理,返回结果 List list = rowHandler.getList(); if (list.size() > 1) { throw new SQLException("Error: executeQueryForObject returned too many results."); } else if (list.size() > 0) { object = list.get(0); } return object; } .... }
protected void executeQueryWithCallback(RequestScope request, Connection conn, Object parameterObject, Object resultObject, RowHandler rowHandler, int skipResults, int maxResults) throws SQLException { ... try { parameterObject = validateParameter(parameterObject); //验证入参 Sql sql = getSql(); //获取SQL对象 errorContext.setMoreInfo("Check the parameter map."); ParameterMap parameterMap = sql.getParameterMap(request, parameterObject);// 入参映射 errorContext.setMoreInfo("Check the result map."); ResultMap resultMap = sql.getResultMap(request, parameterObject); //结果映射 request.setResultMap(resultMap); request.setParameterMap(parameterMap); errorContext.setMoreInfo("Check the parameter map."); Object[] parameters = parameterMap.getParameterObjectValues(request, parameterObject); //获取参数值 errorContext.setMoreInfo("Check the SQL statement."); String sqlString = sql.getSql(request, parameterObject); //获取拼装后的sql语句 errorContext.setActivity("executing mapped statement"); errorContext.setMoreInfo("Check the SQL statement or the result map."); RowHandlerCallback callback = new RowHandlerCallback(resultMap, resultObject, rowHandler); sqlExecuteQuery(request, conn, sqlString, parameters, skipResults, maxResults, callback); //sql执行 errorContext.setMoreInfo("Check the output parameters."); if (parameterObject != null) { postProcessParameterObject(request, parameterObject, parameters); } errorContext.reset(); sql.cleanup(request); notifyListeners(); .... }
public void executeQuery(RequestScope request, Connection conn, String sql, Object[] parameters, int skipResults, int maxResults, RowHandlerCallback callback) throws SQLException { ... PreparedStatement ps = null; ResultSet rs = null; setupResultObjectFactory(request); try { errorContext.setMoreInfo("Check the SQL Statement (preparation failed)."); Integer rsType = request.getStatement().getResultSetType(); //初始化PreparedStatement,设置sql、参数值等 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)."); ps.execute(); //执行 errorContext.setMoreInfo("Check the results (failed to retrieve results)."); // ResultSet处理 rs = handleMultipleResults(ps, request, skipResults, maxResults, callback); } finally { try { closeResultSet(rs); } finally { closeStatement(request.getSession(), ps); } } }