web-dev-qa-db-fra.com

Existe-t-il un moyen de récupérer l'ID d'auto-incrémentation à partir d'une instruction préparée

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.

stmt = conn.createStatement();

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

Toutefois. Et si je veux faire un encart 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);
} 

Y a-t-il un moyen de faire cela que je ne connais pas. Il semble d'après le javadoc que PreparedStatements ne peut pas retourner l'ID généré automatiquement.

58
jW.

Oui. Voir ici . 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);
}
92
Yishai

Il y a plusieurs façons, et il semble que différents pilotes jdbc gèrent les choses un peu différemment, ou pas du tout dans certains cas (certains ne vous donneront que des clés primaires générées automatiquement, pas d'autres colonnes), mais les formes de base sont

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

Ou utilisez ce formulaire:

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

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

Leur façon est de passer l'ID AutoGeneratedKeys comme suit

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

Je fais partie de ceux qui ont parcouru quelques discussions à la recherche d'une solution à ce problème ... et enfin pour que cela fonctionne. POUR CEUX QUI UTILISENT jdbc: Oracle: thin: avec ojdbc6.jar VEUILLEZ PRENDRE NOTE: Vous pouvez utiliser les deux 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 de ne pas utiliser la méthode 1 si vous voulez simplement la valeur de SEQ.Nextval, b'cse il suffit de renvoyer la référence RowID que vous pouvez vous casser la tête en trouvant un moyen de l'utiliser, qui ne convient pas non plus à tous les types de données que vous avez essayé de lancer à! Cela peut fonctionner correctement (retourner la valeur réelle) dans MySQL, DB2 mais pas dans Oracle.

ET, désactivez votre SQL Developer, Toad ou tout client qui utilise la même session de connexion pour effectuer INSERT lorsque vous déboguez. Cela PEUT ne pas vous affecter à chaque fois (appel de débogage) ... jusqu'à ce que vous trouviez que vos applications se bloquent sans exception pendant un certain temps. Oui ... arrêtez sans exception!

2
peterong