PreparedStatement con Statement.RETURN_GENERATED_KEYS


83

La única forma en que algunos controladores JDBC regresan Statement.RETURN_GENERATED_KEYSes hacer algo de lo siguiente:

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 alguna forma de hacer lo mismo con PreparedStatement?


Editar

La razón por la que pregunté si puedo hacer lo mismo con PreparedStatementconsiderar el siguiente escenario:

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

En la USERtabla hay un PRIMARY KEY (USER_ID)que es un BIGINT AUTOINCREMENT(por lo tanto, por qué no lo ve en el SQL_CREATEString.

Ahora, completo el ?using PreparedStatement.setXXXX(index, value). Quiero volver ResultSet rs = PreparedStatement.getGeneratedKeys(). ¿Cómo puedo conseguir esto?


2
Muchas personas entienden mal y usan PreparedStatement # executeUpdate (arg). El documento de Java dice que This method with argument cannot be called on a PreparedStatement or CallableStatement.significa que tenemos que usar executeUpdate () sin argumentos, aunque el executeUpdate(arg)método se puede heredar en la clase PreparedStatement, pero no tenemos que usarlo, de lo contrario obtendremos SQLException.
AmitG

Respuestas:


141

Puede usar el prepareStatementmétodo tomando un intparámetro adicional

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

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

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

Acepté su respuesta porque mostró más formas de lograr el mismo resultado.
Buhake Sindi

67

¿Te refieres a 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);
}

¿Cómo puede ser nulo el conjunto de resultados de claves generadas?
AlikElzin-kilaka

10

Al no tener un compilador para mí en este momento, responderé haciendo 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 entiendes la idea.

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


eso no es lo que estoy buscando. Sé que PreparedStatementes una subclase de Statement.... ver mi publicación actualizada.
Buhake Sindi

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

Si se genera la clave, la clave de lo contrario es clave = 0 si no se genera
Dharmendrasinh Chudasama

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ía liberar su conexión en el bloque final, no fuera de él (obtendrá una conexión si obtiene una excepción de tiempo de ejecución de cualquier tipo)?
Jules

@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
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.