2010-11-19 8 views
62

L'unico modo che alcuni driver JDBC per tornare Statement.RETURN_GENERATED_KEYS è fare qualcosa di quanto segue:PreparedStatement con 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); 
} 

C'è un modo per fare lo stesso con PreparedStatement?


Modifica

La ragione per cui ho chiesto se posso fare lo stesso con PreparedStatement consideri il seguente scenario:

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

Nella tabella USER c'è un PRIMARY KEY (USER_ID) che è un BIGINT AUTOINCREMENT (quindi perché non lo vedi nella stringa SQL_CREATE.

Ora compilo lo ? utilizzando PreparedStatement.setXXXX(index, value). Voglio restituire ResultSet rs = PreparedStatement.getGeneratedKeys(). Come posso raggiungere questo obiettivo?

+2

Molte persone fraintendono e utilizzare PreparedStatement # executeUpdate (arg). Java doc dice 'Questo metodo con argomento non può essere chiamato su PreparedStatement o CallableStatement. Significa che dobbiamo usare executeUpdate() senza argomenti anche se il metodo' executeUpdate (arg) 'può essere ereditato nella classe PreparedStatement ma non abbiamo per usarlo altrimenti otterremo SQLException. – AmitG

risposta

107

è possibile utilizzare il metodo prepareStatement prendendo un ulteriore int parametro

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

Per alcuni driver JDBC (ad esempio, Oracle) è necessario elencare esplicitamente i nomi delle colonne o indici delle chiavi generate:

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

Ho accettato la tua risposta come hai mostrato più modi per ottenere lo stesso risultato. –

8

Non avendo un compilatore per me in questo momento, risponderò con una domanda:

Hai provato questo? Funziona?

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

Disclaimer: Ovviamente, non ho compilato questo, ma si ottiene l'idea.

PreparedStatement è una sottointerfaccia di Statement, quindi non vedo un motivo per cui questo non funzionerebbe, a meno che alcuni driver JDBC non siano corretti.

+0

non è quello che sto cercando so che 'PreparedStatement' è una sottoclasse di' Statement' .... vedi il mio post aggiornato. –

52

Intendi qualcosa del genere?

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 .... Non riuscivo a vederlo. Grazie! –

+0

Come può il set di risultati delle chiavi generate essere nullo? –

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

Non dovresti liberare la tua connessione nel blocco finally, non al di fuori (ti porterai una connessione se ottieni un'eccezione di runtime di qualsiasi tipo)? – Jules

+0

@niraj - invece di ps.RETURN_GENERATED_KEYS possiamo scrivere Statement.RETURN_GENERATED_KEYS perché è una variabile statica nella 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

Se la chiave è stata generata, premere il tasto altrimenti tasto = 0 se non generato –

Problemi correlati