2009-11-20 3 views
14

Sto usando iBatis/Java e Postgres 8.3. Quando faccio un inserto in ibatis ho bisogno dell'id restituito.
ho utilizzare la seguente tabella per descrivere la mia domanda:
CREATE TABLE sometable (id serial NOT NULL, somefield VARCHAR(10));
La Sequenza sometable_id_seq ottiene generati automaticamente eseguendo l'istruzione CREATE.Come restituire id su Inserti con Ibatis (con parola chiave RETURNING)

Al momento io uso la seguente mappa 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> 

Sembra questo è il modo iBATIS di recuperare l'id appena inserito. Ibatis prima esegue un'istruzione INSERT e successivamente chiede la sequenza per l'ultimo id.
Ho dubbi che questo funzionerà con molti inserti concorrenti. (discussed in this question)

mi piacerebbe utilizzare la seguente dichiarazione con ibatis:
INSERT INTO sometable (somefield) VALUES (#value#) RETURNING id;

ma quando provo ad usarlo all'interno di un ibatis <insert> sqlMap non restituisce l'id. Sembra che sia necessario il tag <selectKey>.

Così qui viene la domanda:

come posso utilizzare l'istruzione di cui sopra con iBATIS?

risposta

15

L'elemento <selectKey> è un figlio dell'elemento <insert> e il suo contenuto viene eseguita prima principale INSERT dichiarazione. Puoi usare due approcci.

prendere la chiave dopo aver inserito il record

Questo approccio funziona a seconda del driver. Threading può essere un problema con questo.

Recupero la chiave prima di inserire il record

Questo approccio consente di evitare i problemi di threading, ma è più lavoro. Esempio:

<insert id="insert"> 
    <selectKey keyProperty="myId" 
      resultClass="int"> 
    SELECT nextVal('my_id_seq') 
    </selectKey> 
    INSERT INTO my 
    (myId, foo, bar) 
    VALUES 
    (#myId#, #foo#, #bar#) 
</insert> 

Sul lato Java si può poi fare

Integer insertedId = (Integer) sqlMap.insert("insert", params) 

Questo dovrebbe dare la chiave selezionata dalla sequenza my_id_seq.

+0

questa soluzione risolve i miei timori di concorrenza. Lascia solo la domanda se ibatis può funzionare con una sintassi INSERT INTO .. ​​RETURING ... – Christoph

9

Ecco semplice esempio:

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

E nel codice Java:

Integer id = (Integer) executor.queryForObject("addObject", object); 
object.setId(id); 

questo modo più meglio di utilizzo:

  1. È più semplice;
  2. Non ha richiesto di conoscere il nome della sequenza (cosa solitamente nascosta agli sviluppatori di postgresql).
+0

Questa sarebbe la risposta che stavo cercando ... ma non funziona: quando si usa executer.queryForObject l'ID viene restituito, ma non viene inserito nulla, e quando uso executer.insert viene inserita la riga, ma null è restituito – Christoph

+0

Questo molto strano, perché copio e incollo il mio codice di lavoro. Anche io non capisco - come si può ottenere id senza aggiungere nuovi record? Cosa vedi nel registro iBatis SQL? – leonidv

+2

Sembra che uno di voi abbia attivato il commit automatico e l'altro no. – inanutshellus

Problemi correlati