2

iBatis/Java と Postgres 8.3 を使用しています。Ibatis で挿入を行うときは、ID を返す必要があります。
次の表を使用して質問を説明します
CREATE TABLE sometable ( id serial NOT NULL, somefield VARCHAR(10) );
。シーケンスsometable_id_seqは、create ステートメントを実行することによって自動生成されます。

現時点では、次のSQLマップを使用しています:

<insert id="insertValue" parameterClass="string" >
 INSERT INTO sometable ( somefield ) VALUES ( #value# );
 <selectKey keyProperty="id" resultClass="int">
  SELECT last_value AS id FROM sometable_id_seq
 </selectKey>
</insert>

これは、新しく挿入された ID を取得する ibatis の方法のようです。Ibatis は最初に INSERT ステートメントを実行し、その後シーケンスに最後の ID を要求します。
これが多くの同時挿入で機能するかどうかは疑問です。

これにより問題が発生する可能性はありますか? 間違った挿入のIDを返すのが好きですか?

( ibatis で INSERT .. RETURING .. ステートメントを使用する方法に関する私の関連する質問も参照してください)

4

3 に答える 3

2

これは絶対に間違っています。使用する:

select currval('sometable_id_seq')

またはさらに良い:

INSERT INTO sometable ( somefield ) VALUES ( #value# ) returning id

挿入したIDを返します。

于 2009-11-20T13:22:03.580 に答える
0

簡単な例を次に示します。

<statement id="addObject"
        parameterClass="test.Object"
        resultClass="int">
        INSERT INTO objects(expression, meta, title,
        usersid)
        VALUES (#expression#, #meta#, #title#, #usersId#)
        RETURNING id
</statement>

そしてJavaコードでは:

Integer id = (Integer) executor.queryForObject("addObject", object);
object.setId(id);
于 2009-12-03T20:08:34.693 に答える
0

別の考えがあります。Class :ibatisをデリゲートする insert メソッドを呼び出します。com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate,with the code

 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;
      if (selectKeyStatement != null && !selectKeyStatement.isRunAfterSQL()) {
        keyProperty = selectKeyStatement.getKeyProperty();
        oldKeyValue = PROBE.getObject(param, keyProperty);
        generatedKey = executeSelectKey(sessionScope, trans, ms, param);
        resetKeyValueOnFailure = true;
      }

      StatementScope statementScope = beginStatementScope(sessionScope, ms);
      try {
        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);
      }

      if (selectKeyStatement != null && selectKeyStatement.isRunAfterSQL()) {
        generatedKey = executeSelectKey(sessionScope, trans, ms, param);
      }

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

insert および select 演算子がTransactionにあることがわかります。したがって、挿入メソッドには同時性の問題はないと思います。

于 2012-08-19T12:12:52.810 に答える