首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 数据库 > 其他数据库 >

ibatis访问数据库的大体逻辑

2013-12-15 
ibatis访问数据库的大致逻辑创建SQL_Map_Config.xml文件? ??xml?version1.0?encodingUTF-8????!D

ibatis访问数据库的大致逻辑

    创建SQL_Map_Config.xml文件
? ?
  1. <?xml?version="1.0"?encoding="UTF-8"??>??
  2. <!DOCTYPE?sqlMapConfig????????
  3. ????PUBLIC?"-//ibatis.apache.org//DTD?SQL?Map?Config?2.0//EN"????????
  4. ????"http://ibatis.apache.org/dtd/sql-map-config-2.dtd">??
  5. <sqlMapConfig>??
  6. ????<properties?resource="jdbc.properties"?/>??
  7. ????<transactionManager?type="JDBC">??
  8. ????????<dataSource?type="SIMPLE">??
  9. ????????????<property?name="JDBC.Driver"?value="${jdbc.driverClassName}"?/>??
  10. ????????????<property?name="JDBC.ConnectionURL"?value="${jdbc.url}"?/>??
  11. ????????????<property?name="JDBC.Username"?value="${jdbc.username}"?/>??
  12. ????????????<property?name="JDBC.Password"?value="${jdbc.password}"?/>??
  13. ????????</dataSource>??
  14. ????</transactionManager>??
  15. ????<sqlMap?resource="ibatis/resources/User.xml"?/>??
  16. </sqlMapConfig>??
?这个文件设置了数据库连接的参数,以及存放SQL的SQLMap文件?2.创建SQLMap文件?
  1. <?xml?version="1.0"?encoding="UTF-8"?>??
  2. <!DOCTYPE?sqlMap??????????
  3. ????PUBLIC?"-//ibatis.apache.org//DTD?SQL?Map?2.0//EN"??"http://ibatis.apache.org/dtd/sql-map-2.dtd"> ?
  4. <sqlMap>??
  5. ????<typeAlias?alias="User"?type="cn.yangphere.ibatisdemo.model.User"/>??
  6. ????<select?id="getAllUsers"?resultClass="User">??
  7. ????????select?id?as?userId,?userName?as?username,?password,?mobile,?email??
  8. ????????from?users??
  9. ????</select>??
  10. </sqlMap> ?
??3.java调用
  1. package?ibatis;??
  2. import?ibatis.model.User;??
  3. import?java.io.*;??
  4. import?java.sql.SQLException;??
  5. import?java.util.List;??
  6. import?com.ibatis.common.resources.Resources;??
  7. import?com.ibatis.sqlmap.client.*;??
  8. public?class?IBatisDemo?{??
  9. ????public?static?void?main(String[]?args)?throws?IOException,?SQLException?{??
  10. ????????String?config?=?"ibatis/SqlMapConfig.xml";??
  11. ????????Reader?reader?=?Resources.getResourceAsReader(config);??
  12. ????????SqlMapClient?sqlMap?=?SqlMapClientBuilder.buildSqlMapClient(reader);??
  13. ????????List<User>?list?=?sqlMap.queryForList("getAllUsers");??
  14. ????????for?(User?user?:?list)?{??
  15. ????????????System.out.println(user);??
  16. ????????}??
  17. ????}??
  18. } ?
这样一个基本的ibatis使用例子就完成了??这个调用代码里,有两个方面的操作,
    根据sqlmapconfig.xml文件生成client对象用client对象访问CRUD方法,来访问数据库
??先来看看根据sqlmapconfig.xml文件生成client对象:1.SqlMapClient?sqlMap?=?SqlMapClientBuilder.buildSqlMapClient(reader);??看看buildSqlMapClient方法的代码:
  /**   * Builds an SqlMapClient using the specified reader.根据xml文件输入流 创建一个client对象   * @param reader A Reader instance that reads an sql- map-config.xml file.   *               The reader should read an well formed sql- map-config.xml file.   * @return An SqlMapClient instance.   */  public static SqlMapClient buildSqlMapClient(Reader reader) {//    return new XmlSqlMapClientBuilder().buildSqlMap(reader);    return new SqlMapConfigParser().parse(reader);  }
???2.接着往下看ibatis访问数据库的大体逻辑?SqlMapClient?com.ibatis.sqlmap.engine.builder.xml.SqlMapConfigParser.parse(Reader?reader)
  public SqlMapClient parse(Reader reader) {    try {      if ( vars.sqlMapConfigConv != null) {        reader = vars.sqlMapConfigConv .convertXml(reader);      }      parser.parse(reader);      return vars.client ;    } catch (Exception e) {      throw new NestedRuntimeException("Error occurred.  Cause: " + e, e);    }  }
??这里xml文件的输入流被用来转换sql去了?但是这个方法返回的client并不是直接从这个方法生成的?我们看
public class SqlMapConfigParser extends BaseParser {   public SqlMapConfigParser(XmlConverter sqlMapConfigConv, XmlConverter sqlMapConv) {    super( new Variables());    parser.setValidation( true);    parser.setEntityResolver( new SqlMapClasspathEntityResolver());    vars.sqlMapConfigConv = sqlMapConfigConv;    vars.sqlMapConv = sqlMapConv;    vars.delegate = new SqlMapExecutorDelegate();//直接new了一个    vars.typeHandlerFactory = vars.delegate .getTypeHandlerFactory();    vars.client = new SqlMapClientImpl(vars .delegate );    registerDefaultTypeAliases();    addSqlMapConfigNodelets();    addGlobalPropNodelets();    addSettingsNodelets();    addTypeAliasNodelets();    addTypeHandlerNodelets();    addTransactionManagerNodelets();    addSqlMapNodelets();  }}
?发现SqlMapConfigParser?这个类的构造方法里就有vars.?delegate?=?new?SqlMapExecutorDelegate();//直接new了一个vars.?client?=?new?SqlMapClientImpl(vars?.delegate?);?这两行,生产了client对象 ?至于具体流程 这里不去追究 只需要知道大致是这样就得到了client对象?????用client对象访问CRUD方法,来访问数据库?List<User>?list?=?sqlMap.queryForList("getAllUsers");??这里的client是?SqlMapClientImpl对象这个类包括了所有CRUD方法,?SqlMapClientImpl 实现了ExtendedSqlMapClient接口?ExtendedSqlMapClient接口又继承了SqlMapClient接口?SqlMapClient接口继承了SqlMapExecutor, SqlMapTransactionManager两个接口?SqlMapExecutor, SqlMapTransactionManager这两个接口分别让client获得了CRUD方法和事务控制的能力??有一个图可以简明的表达这个关系:ibatis访问数据库的大体逻辑???我们来看SqlMapClientImpl?里面CRUD方法的代码:?
public class SqlMapClientImpl implements ExtendedSqlMapClient {     public SqlMapExecutorDelegate delegate;     private ThreadLocal localSqlMapSession = new ThreadLocal ();        public Object queryForObject(String id, Object paramObject, Object resultObject) throws SQLException {    return getLocalSqlMapSession().queryForObject(id, paramObject, resultObject);  }  private SqlMapSessionImpl getLocalSqlMapSession() {    SqlMapSessionImpl sqlMapSession = (SqlMapSessionImpl) localSqlMapSession.get();    if (sqlMapSession == null || sqlMapSession.isClosed()) {      sqlMapSession = new SqlMapSessionImpl(this);      localSqlMapSession.set(sqlMapSession);    }    return sqlMapSession;  }}
?queryForObject为例,是获取了SqlMapSessionImpl?对象,然后执行SqlMapSessionImpl?对象里面的queryForObject方法的??我们再来看SqlMapSessionImpl??
public class SqlMapSessionImpl implements SqlMapSession {  protected SqlMapExecutorDelegate delegate;  protected SessionScope session;  protected boolean closed ;  public Object queryForObject(String id, Object paramObject, Object resultObject) throws SQLException {    return delegate.queryForObject(session , id, paramObject, resultObject);  }}
??可以发现?SqlMapSessionImpl?实现了SqlMapSession?接口这个对象有SqlMapExecutorDelegate?CRUD操作代理类对象SessionScope? 对象 里面存了执行数据库操作所需的各种资源和对象(会话)queryForObject方法的实现是通过代理类SqlMapExecutorDelegate?的方法queryForObject??看SqlMapExecutorDelegate?的源码?
 /**   * Execute a select for a single object   *   * @param session      - the session scope   * @param id           - the statement ID   * @param paramObject  - the parameter object   * @param resultObject - the result object (if not supplied or null, a new object will be created)   * @return - the result of the query   * @throws SQLException - if the query fails   */  public Object queryForObject(SessionScope session, String id, Object paramObject, Object resultObject) throws SQLException {    Object object = null;    MappedStatement ms = getMappedStatement(id);    Transaction trans = getTransaction(session);    boolean autoStart = trans == null;    try {      trans = autoStartTransaction(session, autoStart, trans);      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;  }
??首先?MappedStatement ms = getMappedStatement(id); 根据sqlMap里的id 获取到SQL语句对象Transaction trans = getTransaction(session); 从session中获取Transaction事务管理对象?然后RequestScope request = popRequest(session, ms); 从request池中取出request对象?object = ms.executeQueryForObject(request, trans, paramObject, resultObject);执行查询?pushRequest(request);放回request池?autoCommitTransaction(session, autoStart);提交事务??return?object;返回查询结果??????其中?ms.executeQueryForObject(request, trans, paramObject, resultObject);往下看发现其实是GeneralStatement类继承了BaseStatementBaseStatement又实现了MappedStatement?接口?所以这里MappedStatement ms = getMappedStatement(id); 得到的是GeneralStatement实例??
  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();      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);    }  }
??这里可以看到 new 了一个rowHandler?对象 ?然后执行executeQueryWithCallback?方法?然后从rowHandler?对象里获取到结果集list?取list里的第一个元素返回???其中DefaultRowHandler?类也很简单 里面就是一个list?
public class DefaultRowHandler implements RowHandler {  private List list = new ArrayList();  public void handleRow(Object valueObject) {    list.add(valueObject) ;  }  public List getList() {    return list;  }}
???再看executeQueryWithCallback 方法的实现?ibatis.sqlmap.engine.mapping.statement.GeneralStatement.executeQueryWithCallback()?
  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 sql = getSql();      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 了 可以做个输出      System. out.println( sqlString);      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);    }  }
???可以看到 获取参数Map ?和结果集Map ?ParameterMap?,ResultMap?然后是拼接sql语句String sqlString = sql.getSql(request, parameterObject);?//这个就是拼接SQL的方法??再执行sql?? ? ? RowHandlerCallback callback =?new?RowHandlerCallback(resultMap, resultObject, rowHandler);????? sqlExecuteQuery(request, conn, sqlString, parameters, skipResults, maxResults, callback);???接下来是最核心的?到了执行中最核心的一步,也是最后一步: MappedStatement.sqlExecuteQuery()方法,它负责sql的最后执行,内部调用了SqlExecutor.executeQuery()方法ibatis.sqlmap.engine.mapping.statement.GeneralStatement.sqlExecuteQuery()
  protected void sqlExecuteQuery(RequestScope request, Connection conn, String sqlString, Object[] parameters, int skipResults, int maxResults, RowHandlerCallback callback) throws SQLException {    getSqlExecutor().executeQuery(request, conn, sqlString, parameters, skipResults, maxResults, callback);  }
??先获取SqlExecutor对象com.ibatis.sqlmap.engine.execution.SqlExecutor.executeQuery()?
 /**   * Long form of the method to execute a query   *   * @param request - the request scope   * @param conn - the database connection   * @param sql - the SQL statement to execute   * @param parameters - the parameters for the statement   * @param skipResults - the number of results to skip   * @param maxResults - the maximum number of results to return   * @param callback - the row handler for the query   *   * @throws SQLException - if the query fails   */  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;    try {      errorContext.setMoreInfo( "Check the SQL Statement (preparation failed).");      Integer rsType = request.getStatement().getResultSetType();      if (rsType != null) {        ps = conn.prepareStatement(sql, rsType.intValue(), ResultSet.CONCUR_READ_ONLY );      } else {        ps = conn.prepareStatement(sql);      }      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();      rs = getFirstResultSet(ps);      if (rs != null) {        errorContext.setMoreInfo( "Check the results (failed to retrieve results).");        handleResults(request, rs, skipResults, maxResults, callback);      }      // clear out remaining results      while (ps.getMoreResults());    } finally {      try {        closeResultSet(rs);      } finally {        closeStatement(ps);      }    }  }
?可以发现 这是ibatis访问数据库的最后一步了 其实就是我们以前用的jdbc访问数据库的代码这一步可以得到最终拼接完成的SQL?
      ps = conn.prepareStatement(sql);      ps.execute();      rs = getFirstResultSet(ps);handleResults(request, rs, skipResults, maxResults, callback); rs放入callback
?????????

热点排行