2010-11-19 17 views
62

La única forma en que algunos controladores JDBC para volver Statement.RETURN_GENERATED_KEYS es hacer algo de lo siguiente: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); 
} 

¿Hay una manera de hacer lo mismo con PreparedStatement?


Editar

La razón por la que pregunté si puedo hacer lo mismo con PreparedStatement cuenta la situación siguiente:

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

En la tabla USER hay un PRIMARY KEY (USER_ID) que es un BIGINT AUTOINCREMENT (de ahí por qué no lo ves en el SQL_CREATE String.

Ahora llenando el ? usando PreparedStatement.setXXXX(index, value). Quiero devolver ResultSet rs = PreparedStatement.getGeneratedKeys(). ¿Cómo puedo conseguir esto?

+2

Mucha gente no entiende y utilizan PreparedStatement # executeUpdate (arg). El documento Java dice 'Este método con argumento no se puede invocar en un PreparedStatement o CallableStatement. Significa que tenemos que usar executeUpdate() sin argumento aunque el método' executeUpdate (arg) 'se puede heredar en la clase PreparedStatement, pero no tenemos para usarlo de lo contrario obtendremos SQLException. – AmitG

Respuesta

107

También se puede usar el método prepareStatement tomar un int parámetro adicional

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

Para algunos controladores JDBC (por ejemplo, Oracle) tiene que enumerar explícitamente los nombres de las columnas o índices de las claves generadas:

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

He aceptado su respuesta ya que ha mostrado más formas de lograr el mismo resultado. –

8

No tener un compilador por mí en este momento, voy a responder con una pregunta:

¿Has probado esto? ¿Funciona?

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); 
} 

Descargo de responsabilidad: Obviamente, no he compilado esto, pero se entiende la idea.

PreparedStatement es una subinterfaz de Statement, por lo que no veo una razón por la que esto no funcione, a menos que algunos controladores JDBC tengan errores.

+0

eso no es lo que estoy buscando. Sé que 'PreparedStatement' es una subclase de' Statement' .... vea mi publicación actualizada. –

52

¿Quiere decir algo como esto?

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 ... No pude verlo. ¡Gracias! –

+0

¿Cómo puede ser nulo el resultado de las claves generadas? –

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

¿No deberías estar liberando tu conexión en el bloque finally, no fuera de él (tendrás una conexión si obtienes una excepción de tiempo de ejecución de cualquier tipo)? – Jules

+0

@niraj - en lugar de ps.RETURN_GENERATED_KEYS podemos escribir Statement.RETURN_GENERATED_KEYS porque es una variable estática en la clase 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 se genera la clave, entonces la clave de lo contrario es clave = 0 si no se genera –

Cuestiones relacionadas