2008-09-16 7 views
16

Des conseils sur la manière de lire le champ d'identité auto-incrémenté affecté à l'enregistrement nouvellement créé à partir d'un appel java.sql.Statement.executeUpdate? Je sais comment faire cela en SQL pour plusieurs plates-formes DB, mais j'aimerais savoir quelles interfaces indépendantes de base de données existent dans java.sql pour ce faire, et toute contribution sur l'expérience des gens avec cela sur les plates-formes DB.Accès au champ d'identité d'incrémentation automatique après l'insertion SQL dans Java

Répondre

23

Le snibblet de code suivant devrait ya faire »:

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

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

Ceci est connu pour travailler sur les bases de données suivantes

  • Derby
  • MySQL
  • SQL Server

Pour les bases de données où e cela ne fonctionne pas (HSQLDB, Oracle, PostgreSQL, etc), vous aurez besoin de futz avec des astuces spécifiques à la base de données. Par exemple, sur PostgreSQL, vous appelez SELECT NEXTVAL(...) pour la séquence en question.

Notez que les paramètres pour executeUpdate(...) sont analogues.

+0

Légère faute de frappe dans la réponse ci-dessus "res.getInt (0)" devrait être "res.getInt (1)". Impossible de me modifier pour le moment. Un jour :) – Sean

+2

Stupide 1-indexed API. Si seulement ils avaient écouté la sagesse de Dijkstra ... –

+0

Probablement une ancienne publication, mais avez-vous un lien vers le papier de Dijkstra où il explique pourquoi les tableaux 0-index sont meilleurs, j'ai vu il y a longtemps mais je ne me souviens pas où. – Triztian

0

J'ai toujours dû faire un deuxième appel en utilisant une requête après l'insertion.

Vous pouvez utiliser un ORM comme hibernate. Je pense que ça fait ça pour toi.

+0

Un deuxième appel est dangereux car il rencontre des problèmes de synchronisation. De manière optimale, l'obtention de la clé générée automatiquement et de l'INSERT réel doit être atomique, soit en une opération, soit en tant que deux dans la même transaction (par exemple PostgreSQL). –

+0

Toutes les bases de données avec lesquelles j'ai travaillé supportent l'ID après insertion. La base de données gère la synchronisation. C'est basé sur votre connexion, et le dernier insert. Donc, ce n'est pas dangereux si votre base de données fournit ce moyen d'accéder aux données, ou si vous utilisez une transaction. – ScArcher2

0

@ ScArcher2: Je suis d'accord, Hibernate a besoin de faire un second appel pour obtenir l'identité nouvellement généré une stratégie de SAUF SI générateur de pointe est utilisée (séquence, hilo ...)

2
ResultSet keys = statement.getGeneratedKeys(); 

plus tard, juste itérer sur ResultSet.

+0

Wow, je ne savais pas à ce sujet. Je travaille avec java depuis 1.2, et je suppose que je n'ai pas remarqué quand cette méthode a été ajoutée. – ScArcher2

0

@ ScArcher2

Faire un deuxième appel est extrêmement dangereux. Le processus de INSERT et la sélection des clés générées automatiquement résultantes doivent être atomiques, sinon vous risquez de recevoir des résultats incohérents sur la sélection de touche. Considérons deux INSERT s asynchrones où ils se terminent tous les deux avant de pouvoir sélectionner les clés générées. Quel processus obtient quelle liste de clés? La plupart des ORM inter-bases de données doivent faire des choses ennuyeuses comme le verrouillage de threads en cours de processus afin de garder les résultats déterministes. C'est pas quelque chose que vous voulez faire à la main, surtout si vous utilisez une base de données qui supporte la récupération de clé atomique (HSQLDB est le seul que je connaisse qui ne le fait pas).

+0

C'est quelque chose que gère la base de données. Cela fonctionne même avec HSQLDB. Ils fournissent une fonction IDENTITY() que vous pouvez appeler après avoir inséré une valeur pour obtenir le dernier ID d'insertion. C'est dans leur documentation, et ce n'est pas "extrêmement dangereux". Je pense que vous êtes mal informé. – ScArcher2

+0

Malheureusement, cette fonction IDENTITY() obtient le dernier identifiant INSERT, c'est-à-dire le dernier qui a été inséré. Si deux threads effectuent des insertions de façon asynchrone, il est possible qu'un thread reçoive l'ID pour l'autre. –

Questions connexes