2010-11-19 3 views
62

La seule façon que certains pilotes JDBC pour revenir Statement.RETURN_GENERATED_KEYS est de faire quelque chose de ce qui suit:PreparedStatement avec Statement.RETURN_GENERATED_KEYS

long key = -1L; 
Statement statement = connection.createStatement(); 
statement.executeUpdate(YOUR_SQL_HERE, Statement.RETURN_GENERATED_KEYS); 
ResultSet rs = statement.getGeneratedKeys(); 
if (rs != null && rs.next()) { 
    key = rs.getLong(1); 
} 

Est-il possible de faire la même chose avec PreparedStatement?


Modifier

La raison pour laquelle j'ai demandé si je peux faire la même chose avec PreparedStatement du scénario suivant:

private static final String SQL_CREATE = 
      "INSERT INTO 
      USER(FIRST_NAME, MIDDLE_NAME, LAST_NAME, EMAIL_ADDRESS, DOB) 
      VALUES (?, ?, ?, ?, ?)"; 

Dans le tableau USER il y a une PRIMARY KEY (USER_ID) qui est un BIGINT AUTOINCREMENT (par conséquent, pourquoi vous ne le voyez pas dans la chaîne SQL_CREATE

Maintenant, je remplis le ? en utilisant PreparedStatement.setXXXX(index, value). Je veux retourner ResultSet rs = PreparedStatement.getGeneratedKeys(). Comment puis-je atteindre cet objectif?

+2

Beaucoup de gens comprennent mal et utilisent PreparedStatement # executeUpdate (arg). Java doc indique 'Cette méthode avec argument ne peut pas être appelée sur PreparedStatement ou CallableStatement.' Cela signifie que nous devons utiliser executeUpdate() sans argument même si la méthode' executeUpdate (arg) 'peut être héritée dans la classe PreparedStatement mais nous n'avons pas pour l'utiliser sinon nous obtiendrons SQLException. – AmitG

Répondre

107

Vous pouvez utiliser la méthode prepareStatement prendre un paramètre int supplémentaire

PreparedStatement ps = con.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS) 

Pour certains pilotes JDBC (par exemple, Oracle), vous devez lister explicitement les noms de colonnes ou d'indices des clés générées:

PreparedStatement ps = con.prepareStatement(sql, new String[]{"USER_ID"}) 
+0

J'ai accepté votre réponse car vous avez montré plus de façons d'atteindre le même résultat. –

8

Ne pas avoir un compilateur en moi en ce moment, je vais répondre en posant une question:

Avez-vous essayé? Est-ce que ça marche? Clause de non-responsabilité: De toute évidence, je n'ai pas compilé cela, mais vous avez l'idée.

PreparedStatement est une sous-interface de Statement, donc je ne vois pas pourquoi cela ne fonctionnerait pas, sauf si certains pilotes JDBC sont buggés.

+0

ce n'est pas ce que je cherche Je sais que 'PreparedStatement' est une sous-classe de' Statement' .... voir ma mise à jour post. –

52

Vous voulez dire quelque chose comme ça?

long key = -1L; 

PreparedStatement preparedStatement = connection.prepareStatement(YOUR_SQL_HERE, PreparedStatement.RETURN_GENERATED_KEYS); 
preparedStatement.setXXX(index, VALUE); 
preparedStatement.executeUpdate(); 

ResultSet rs = preparedStatement.getGeneratedKeys(); 

if (rs.next()) { 
    key = rs.getLong(1); 
} 
+0

Bingo .... Je ne pouvais pas le voir. Merci! –

+0

Comment l'ensemble de résultats des clés générées peut-il être nul? –

0
private void alarmEventInsert(DriveDetail driveDetail, String vehicleRegNo, int organizationId) { 

    final String ALARM_EVENT_INS_SQL = "INSERT INTO alarm_event (event_code,param1,param2,org_id,created_time) VALUES (?,?,?,?,?)"; 
    CachedConnection conn = JDatabaseManager.getConnection(); 
    PreparedStatement ps = null; 
    ResultSet generatedKeys = null; 
    try { 
     ps = conn.prepareStatement(ALARM_EVENT_INS_SQL, ps.RETURN_GENERATED_KEYS); 
     ps.setInt(1, driveDetail.getEventCode()); 
     ps.setString(2, vehicleRegNo); 
     ps.setString(3, null); 
     ps.setInt(4, organizationId); 
     ps.setString(5, driveDetail.getCreateTime()); 
     ps.execute(); 
     generatedKeys = ps.getGeneratedKeys(); 
     if (generatedKeys.next()) { 
      driveDetail.setStopDuration(generatedKeys.getInt(1)); 
     } 
    } catch (SQLException e) { 
     e.printStackTrace(); 
     logger.error("Error inserting into alarm_event : {}", e 
       .getMessage()); 
     logger.info(ps.toString()); 
    } finally { 
     if (ps != null) { 
      try { 

       if (ps != null) 
        ps.close(); 
      } catch (SQLException e) { 
       logger.error("Error closing prepared statements : {}", e 
         .getMessage()); 
      } 
     } 
    } 
    JDatabaseManager.freeConnection(conn); 
} 
+1

Ne devriez-vous pas libérer votre connexion dans le bloc finally, pas à l'extérieur de celui-ci (vous allez poirier une connexion si vous obtenez une exception d'exécution de quelque sorte que ce soit)? – Jules

+0

@niraj - au lieu de ps.RETURN_GENERATED_KEYS, nous pouvons écrire Statement.RETURN_GENERATED_KEYS car il s'agit d'une variable statique dans la classe java.sql.Statement. – AmitG

0
String query = "INSERT INTO ...."; 
PreparedStatement preparedStatement = connection.prepareStatement(query, PreparedStatement.RETURN_GENERATED_KEYS); 

preparedStatement.setXXX(1, VALUE); 
preparedStatement.setXXX(2, VALUE); 
.... 
preparedStatement.executeUpdate(); 

ResultSet rs = preparedStatement.getGeneratedKeys(); 
int key = rs.next() ? rs.getInt(1) : 0; 

if(key!=0){ 
    System.out.println("Generated key="+key); 
} 
+0

Si la clé est générée, alors la clé sinon la clé = 0 si elle n'est pas générée –

Questions connexes