tags:

views:

7856

answers:

5

Any advise on how to read auto incrementing identity field assigned to newly created record from call through java.sql.Statement.executeUpdate ?

I know how to do this in SQL for several DB platforms, but would like to know what database independent interfaces exist in java.sql to do this, and any input on peoples' experience with this across DB platforms.

A: 

I've always had to make a second call using query after the insert.

You could use an ORM like hibernate. I think it does this stuff for you.

ScArcher2
A second call is dangerous because it runs into synchronization issues. Optimally, getting the auto-generated key and the actual INSERT should be atomic, either as one operation or as two within the same transaction (e.g. PostgreSQL).
Daniel Spiewak
All the databases I've worked with support getting the id after insert. The database handles the synchronization. It's based on your connection, and the last insert. So it's not dangerous if your database provides that way of accessing the data, or if you are using a transaction.
ScArcher2
+10  A: 

The following snibblet of code should do ya':

PreparedStatement stmt = conn.prepareStatement(sql, 
                                 Statement.RETURN_GENERATED_KEYS);
// ...

ResultSet res = stmt.getGeneratedKeys();
while (res.next())
    System.out.println("Generated key: " + res.getInt(1));

This is known to work on the following databases

  • Derby
  • MySQL
  • SQL Server

For databases where it doesn't work (HSQLDB, Oracle, PostgreSQL, etc), you will need to futz with database-specific tricks. For example, on PostgreSQL you would make a call to SELECT NEXTVAL(...) for the sequence in question.

Note that the parameters for executeUpdate(...) are analogous.

Daniel Spiewak
Slight typo in answer above "res.getInt(0)" should be "res.getInt(1)". Can't edit myself yet. Someday :)
Sean
Stupid 1-indexed API. If only they had heeded Dijkstra's wisdom...
Daniel Spiewak
A: 

@ScArcher2 : I agree, Hibernate needs to make a second call to get the newly generated identity UNLESS an advanced generator strategy is used (sequence, hilo...)

Alexandre Victoor
+2  A: 
ResultSet keys = statement.getGeneratedKeys();

Later, just iterate over ResultSet.

Kind Regards

marcospereira
Wow, I didn't know about that. I've been working with java since 1.2, and I guess I didn't notice when this method was added.
ScArcher2
A: 

@ScArcher2

Making a second call is extremely dangerous. The process of INSERTing and selecting the resultant auto-generated keys must be atomic, otherwise you may receive inconsistent results on the key select. Consider two asynchronous INSERTs where they both complete before either has a chance to select the generated keys. Which process gets which list of keys? Most cross-database ORMs have to do annoying things like in-process thread locking in order to keep results deterministic. This is not something you want to do by hand, especially if you are using a database which does support atomic generated key retrieval (HSQLDB is the only one I know of which does not).

Daniel Spiewak
This is something the database handles. It even works with HSQLDB. They provide an IDENTITY() function you can call after you insert a value to get the last insert id. It's in their documentation, and it's not "extremely dangerous". I think you are misinformed.
ScArcher2
Unfortunately, that IDENTITY() function gets the last INSERT id, meaning the very last one which was inserted. If two threads are performing inserts asynchronously there will be the possibility of one thread getting the ID meant for the other.
Daniel Spiewak