tjuxiaoqiang 发表于 2013-1-29 14:34:26

ibatis中selectKey的用法与源码

最近用到插入oracle数据库时,主键id是sequnce自动生成,具体写法如下
对于oracle:
      <insert id="insertUser" parameterClass="ibatis.User">
         <selectKey resultClass="long" keyProperty="id">
            select SEQ_USER_ID.nextval as id from dual
          </selectKey>
         insert into user
          (id,name,password)
          values
          (#id#,#name#,#password#)
      </insert>
对于mysql:
      <insert id="insertUser" parameterClass="ibatis.User">
          insert into user
          (name,password)
          values
          (#name#,#password#)
         <selectKey resultClass="long" keyProperty="id">   
             SELECT LAST_INSERT_ID() AS ID   
      </selectKey>   
      </insert>

上面是两种数据库的实现。

下面我们看看源码是如何做的
//-- Basic Methods
/**
   * Call an insert statement by ID
   *
   * @param sessionScope - the session
   * @param id      - the statement ID
   * @param param   - the parameter object
   * @return - the generated key (or null)
   * @throws SQLException - if the insert fails
   */
public Object insert(SessionScope sessionScope, String id, Object param) throws SQLException {
    Object generatedKey = null;

    MappedStatement ms = getMappedStatement(id);
    Transaction trans = getTransaction(sessionScope);
    boolean autoStart = trans == null;

    try {
       //开始事务
      trans = autoStartTransaction(sessionScope, autoStart, trans);

      SelectKeyStatement selectKeyStatement = null;
      if (ms instanceof InsertStatement) {
      selectKeyStatement = ((InsertStatement) ms).getSelectKeyStatement();
      }

      // Here we get the old value for the key property. We'll want it later if for some reason the
      // insert fails.
      Object oldKeyValue = null;
      String keyProperty = null;
      boolean resetKeyValueOnFailure = false;
      //对于oracle适用于执行insert之前执行selectKey获取id值
      if (selectKeyStatement != null && !selectKeyStatement.isRunAfterSQL()) {
      keyProperty = selectKeyStatement.getKeyProperty();
      oldKeyValue = PROBE.getObject(param, keyProperty);
      //sequnce获取id的值
      generatedKey = executeSelectKey(sessionScope, trans, ms, param);
      resetKeyValueOnFailure = true;
      }

      StatementScope statementScope = beginStatementScope(sessionScope, ms);
      try {
      //执行sql语句
      ms.executeUpdate(statementScope, trans, param);
      }catch (SQLException e){
      // uh-oh, the insert failed, so if we set the reset flag earlier, we'll put the old value
      // back...
      if(resetKeyValueOnFailure) PROBE.setObject(param, keyProperty, oldKeyValue);
      // ...and still throw the exception.
      throw e;
      } finally {
      endStatementScope(statementScope);
      }
      //对于mysql适用于执行完insert后,获取id值
      if (selectKeyStatement != null && selectKeyStatement.isRunAfterSQL()) {
      generatedKey = executeSelectKey(sessionScope, trans, ms, param);
      }
      //提交事务
      autoCommitTransaction(sessionScope, autoStart);
    } finally {
    //结束事务
      autoEndTransaction(sessionScope, autoStart);
    }

    return generatedKey;
}
页: [1]
查看完整版本: ibatis中selectKey的用法与源码