ibatis代码分析——简要过程说明

   不管是使用spring框架集成ibatis还是直接使用ibatis,ibatis经历的第一步都是装载SqlMapConfig.xml文件,由于本文只是分析一下ibatis的代码,所以已单纯使用ibatis为例:

public static void main(String[] args) {
        // TODO Auto-generated method stub
        String resource = "dal/sqlmap-config.xml";
        Reader reader = null;
        try {
            reader = Resources.getResourceAsReader(resource);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

//        SqlMapClientBuilder xmlBuilder = new SqlMapClientBuilder();
        SqlMapClient sqlMapClient = SqlMapClientBuilder.buildSqlMapClient(reader);

        try {
            sqlMapClient.startTransaction();
            User user = new User();
            user.setName("tony");
            user.setSex(0);

            sqlMapClient.insert("insertUser", user);
            sqlMapClient.commitTransaction();
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally{
            try {
                sqlMapClient.endTransaction();
                
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
}

 SqlMapClientBuilder会制造一个sqlMapClient,所以是我们使用ibatis的入口。

一旦我们拥有了这个入口,我们就能执行sql操作了,以上例中的sqlMapClient.insert("insertUser", user) 为例来说明执行这条sql的时候发生了一些什么事情。

  • SqlMapExecutor

sqlMapClient拿着一个statement的id和一个参数对象跑到SqlMapExecutor面前说,你帮我处理一下这两个东西。SqlMapExecutor说好的,然后转身把这个任务转发给了它的玄孙:

SqlMapClientImpl。SqlMapClientImpl看着太公交给他的任务,觉得由他自己来做不是很保险,于是又把它交给了同宗的叔叔SqlMapSessionImpl,让这个苦命的叔叔在他自己的会话里把这件

事情给办好。而这位叔叔对于这份苦差事非常厌倦,就把它给外包了,就这样通过层层的外包,最后来到了GeneralStatement 手上。

  • GeneralStatement
public int executeUpdate(RequestScope request, Transaction trans, Object parameterObject)
      throws SQLException {
    ErrorContext errorContext = request.getErrorContext();
    errorContext.setActivity("preparing the mapped statement for execution");
    errorContext.setObjectId(this.getId());
    errorContext.setResource(this.getResource());

    request.getSession().setCommitRequired(true);

    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);

      int rows = 0;

      errorContext.setMoreInfo("Check the parameter map.");
      Object[] parameters = parameterMap.getParameterObjectValues(request, parameterObject);


      errorContext.setMoreInfo("Check the SQL statement.");
      String sqlString = sql.getSql(request, parameterObject);

      errorContext.setActivity("executing mapped statement");
      errorContext.setMoreInfo("Check the statement or the result map.");
      rows = sqlExecuteUpdate(request, trans.getConnection(), sqlString, parameters);


      errorContext.setMoreInfo("Check the output parameters.");
      if (parameterObject != null) {
        postProcessParameterObject(request, parameterObject, parameters);
      }

      errorContext.reset();
      sql.cleanup(request);
      notifyListeners();
      return rows;
    } 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);
    }
  }

 其中标为橙色部分的是几个关键点。ParameterMap负责将sql的insert/update/select/delete参数做映射,ResultMap负责将sql语句执行的结果映射到具体的java对象。

parameterMap.getParameterObjectValues(reqeust,parameterObject)将sql语句中的?与参数对应起来,比如:insert into userinfo(name,sex) values(?,?)就有[tony, 0]与之对应。

剩下的事情就变得容易了,这时SqlExecutor 跳出来说,下面就交给我了。

  • SqlExecutor

SqlExecutor一手拿着sql,一手拿着参数,肩上挂着请求,头上顶着链接叫嚣着,快快,快把PreparedStatement给我准备好,我要生了。

public int executeUpdate(RequestScope request, Connection conn, String sql, Object[] parameters) throws SQLException {
    ErrorContext errorContext = request.getErrorContext();
    errorContext.setActivity("executing update");
    errorContext.setObjectId(sql);
    PreparedStatement ps = null;
    setupResultObjectFactory(request);
    int rows = 0;
    try {
      errorContext.setMoreInfo("Check the SQL Statement (preparation failed).");
      ps = prepareStatement(request.getSession(), conn, sql);
      setStatementTimeout(request.getStatement(), ps);
      errorContext.setMoreInfo("Check the parameters (set parameters failed).");
      request.getParameterMap().setParameters(request, ps, parameters);
      errorContext.setMoreInfo("Check the statement (update failed).");
      ps.execute();
      rows = ps.getUpdateCount();
    } finally {
      closeStatement(request.getSession(), ps);
    }
    return rows;
  }

 于是乎数据就被生了下来。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值