PreparedStatement avec Statement.RETURN_GENERATED_KEYS


83

La seule façon pour certains pilotes JDBC de revenir Statement.RETURN_GENERATED_KEYSest d'effectuer l'une des opérations suivantes:

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

Y a-t-il un moyen de faire la même chose avec PreparedStatement?


Éditer

La raison pour laquelle j'ai demandé si je pouvais faire de même avec PreparedStatementconsidérez le scénario suivant:

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

Dans le USERtableau, il y a un PRIMARY KEY (USER_ID)qui est un BIGINT AUTOINCREMENT(d'où la raison pour laquelle vous ne le voyez pas dans SQL_CREATEString.

Maintenant, je renseigne l' ?utilisation PreparedStatement.setXXXX(index, value). Je veux revenir ResultSet rs = PreparedStatement.getGeneratedKeys(). Comment puis-je atteindre cet objectif?


2
Beaucoup de gens comprennent mal et utilisent PreparedStatement # executeUpdate (arg). Java doc dit que This method with argument cannot be called on a PreparedStatement or CallableStatement.cela signifie que nous devons utiliser executeUpdate () sans argument même si la executeUpdate(arg)méthode peut être héritée dans la classe PreparedStatement mais nous n'avons pas à l'utiliser sinon nous obtiendrons SQLException.
AmitG

Réponses:


141

Vous pouvez soit utiliser la prepareStatementméthode en prenant un intparamètre supplémentaire

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

Pour certains pilotes JDBC (par exemple, Oracle), vous devez répertorier explicitement les noms de colonne ou les index des clés générées:

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

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

67

Tu veux dire quelque chose comme ca?

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

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

10

N'ayant pas de compilateur par moi pour le moment, je répondrai en posant une question:

Avez-vous essayé cela? Est-ce que ça marche?

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

Avertissement: de toute évidence, je n'ai pas compilé ceci, mais vous voyez l'idée.

PreparedStatement est une sous-interface de Statement , donc je ne vois pas pourquoi cela ne fonctionnerait pas, à moins que certains pilotes JDBC soient bogués.


ce n'est pas ce que je recherche Je sais que PreparedStatementc'est une sous-classe de Statement.... voir mon post mis à jour.
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 la clé est générée, la clé sinon la clé = 0 si elle n'est pas générée
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
Ne devriez-vous pas libérer votre connexion dans le bloc finally, pas à l'extérieur (vous perdrez une connexion si vous obtenez une exception d'exécution de quelque nature que ce soit)?
Jules

@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
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.