2009-11-20 16 views
2

我使用的是iBatis/Java和Postgres 8.3。 當我在ibatis中進行插入操作時,我需要返回id。
我用下面的表描述我的問題:
CREATE TABLE sometable (id serial NOT NULL, somefield VARCHAR(10));
的序列sometable_id_seq得到通過運行create語句自動生成。使用ibatis修改新插入的行的Ids時的併發問題

在我使用下面的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?

(參見我的有關問題,有關how to get ibatis to use the INSERT .. RETURING .. statements

回答

2

這肯定是不對的。用途:

select currval('sometable_id_seq') 

或更好:

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

將返回你插入的ID。

+0

所以你認爲它會導致問題。我的另一個問題是關於如何獲取INSERT INTO .. RETURNING ..語句到ibatis(因爲我不能在這裏發佈鏈接,所以我在問題的末尾添加了它) – Christoph 2009-11-20 14:07:50

+0

當然會。試試psql的2個連接。 至於ibatis - 我不知道它是什麼,但它看起來與java有關 - 這意味着我無法幫助。 – 2009-11-20 14:55:16

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

我有另一個想法。 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); 
    } 

可以看出,插入和選擇操作是在交易。所以我認爲插入方法沒有共同性問題。