2009-09-03 5 views
48

Existe-t-il un moyen de récupérer la clé générée automatiquement à partir d'une requête DB lors de l'utilisation d'une requête Java avec des instructions préparées. Par exemple, je sais que AutoGeneratedKeys peut fonctionner comme suit.Existe-t-il un moyen de récupérer l'ID autoincrement à partir d'une instruction préparée?

stmt = conn.createStatement(); 

stmt.executeUpdate(sql, Statement.RETURN_GENERATED_KEYS); 
if(returnLastInsertId) { 
    ResultSet rs = stmt.getGeneratedKeys(); 
    rs.next(); 
    auto_id = rs.getInt(1); 
} 

Cependant. Que faire si je veux faire une insertion avec une déclaration préparée.

String sql = "INSERT INTO table (column1, column2) values(?, ?)"; 
stmt = conn.prepareStatement(sql); 

//this is an error 
stmt.executeUpdate(Statement.RETURN_GENERATED_KEYS); 
if(returnLastInsertId) { 
    //this is an error since the above is an error 
    ResultSet rs = stmt.getGeneratedKeys(); 
    rs.next(); 
    auto_id = rs.getInt(1); 
} 

Existe-t-il un moyen de le faire que je ne connais pas. Il semble à partir du javadoc que PreparedStatements ne peut pas renvoyer l'ID généré automatiquement.

+0

returnLastInsertId où vous obtenez cette variable – dedpo

Répondre

84

Oui. Voir here. Section 7.1.9. Changez votre code pour:

String sql = "INSERT INTO table (column1, column2) values(?, ?)"; 
stmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS); 


stmt.executeUpdate(); 
if(returnLastInsertId) { 
    ResultSet rs = stmt.getGeneratedKeys(); 
    rs.next(); 
    auto_id = rs.getInt(1); 
} 
+0

Cela ne fonctionne pas d'oracle. –

+8

@JafarAli, cette question concerne mysql. Dans Oracle, vous devez spécifier [la colonne générée] (https://community.oracle.com/thread/338591) ou utiliser l'identifiant de ligne. – Yishai

+1

Avez-vous oublié de 'rs.close()'? Est-ce nécessaire ? – Winter

2

Oui, il y a un moyen. Je viens de trouver cette cachette dans le doc java.

Ils est une façon de passer l'id AutoGeneratedKeys comme suit

String sql = "INSERT INTO table (column1, column2) values(?, ?)"; 
stmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS); 
3

Il y a deux façons, et il semble choses différentes poignées pilotes JDBC un peu différent, ou pas du tout dans certains cas (certains ne vous donnez AutoGénéré clés primaires, pas les autres colonnes), mais les formes de base sont

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

Ou utiliser ce formulaire:

String autogenColumns[] = {"column1","column2"}; 
stmt = conn.prepareStatement(sql, autogenColumns) 
1

Je suis l'un de ceux qui ont navigué à travers quelques threads à la recherche d'une solution à ce problème ... et enfin le faire fonctionner. Pour les utilisateurs jdbc: oracle: thin: avec ojdbc6.jar S'IL VOUS PLAÎT PRENDRE NOTE: Vous pouvez utiliser des méthodes: (Méthode 1)

Try{ 
    String yourSQL="insert into Table1(Id,Col2,Col3) values(SEQ.nextval,?,?)"; 
    myPrepStatement = <Connection>.prepareStatement(yourSQL, Statement.RETURN_GENERATED_KEYS); 
    myPrepStatement.setInt(1, 123); 
    myPrepStatement.setInt(2, 123); 

    myPrepStatement.executeUpdate(); 
    ResultSet rs = getGeneratedKeys; 
    if(rs.next()) { 
     java.sql.RowId rid=rs.getRowId(1); 
     //what you get is only a RowId ref, try make use of it anyway U could think of 
     System.out.println(rid); 
    } 
} catch (SQLException e) { 
    // 
} 

(Méthode 2)

Try{ 
    String yourSQL="insert into Table1(Id,Col2,Col3) values(SEQ.nextval,?,?)"; 
    //IMPORTANT: here's where other threads don tell U, you need to list ALL cols 
    //mentioned in your query in the array 
    myPrepStatement = <Connection>.prepareStatement(yourSQL, new String[]{"Id","Col2","Col3"}); 
    myPrepStatement.setInt(1, 123); 
    myPrepStatement.setInt(2, 123); 
    myPrepStatement.executeUpdate(); 
    ResultSet rs = getGeneratedKeys; 
    if(rs.next()) { 
    //In this exp, the autoKey val is in 1st col 
    int id=rs.getLong(1); 
    //now this's a real value of col Id 
    System.out.println(id); 
    } 
} catch (SQLException e) { 
    // 
} 

Fondamentalement, essayez pas utilisé Method1 si vous voulez juste la valeur de SEQ.Nextval, b'cse il suffit de retourner le ref de RowID que vous pouvez craquer votre façon de le trouver, qui ne correspond pas à tous les types de données que vous avez essayé de le faire! Cela peut fonctionner correctement (return val val) dans MySQL, DB2 mais pas dans Oracle. ET, éteignez votre SQL Developer, Toad ou tout autre client qui utilise la même session de connexion pour faire INSERT lorsque vous déboguez. Il PEUT ne pas vous affecter à chaque fois (appel de débogage) ... jusqu'à ce que vous trouviez vos applications geler sans exception pendant un certain temps. Oui ... halte sans exception!

+0

'executeUpdate()' ne retourne pas un 'ResultSet', il renvoie un' int', qui est le nombre de mises à jour. Vous devez récupérer les clés générées séparément. Voir les réponses existantes, et le Javadoc pour l'amour du ciel. -1. [Encore.] (Http://stackoverflow.com/questions/14844864/jdbc-preparedstatement-always-returns-1-as-auto-generated-key) S'il vous plaît arrêtez de poster vos devinettes non testées ici. – EJP

+0

Désolé, mon erreur. Je les ai corrigés. – peterong

-1
Connection connection=null; 
    int generatedkey=0; 
    PreparedStatement pstmt=connection.prepareStatement("Your insert query"); 
    ResultSet rs=pstmt.getGeneratedKeys(); 
    if (rs.next()) { 
     generatedkey=rs.getInt(1); 
       System.out.println("Auto Generated Primary Key " + generatedkey); 
    } 
Questions connexes