web-dev-qa-db-fra.com

utilisation de JDBC PreparedStatement dans un batch

J'utilise des lots de Statements pour interroger ma base de données. J'ai fait quelques recherches maintenant et je veux réécrire mon application pour utiliser preparedStatement à la place, mais j'ai du mal à comprendre comment ajouter des requêtes à un preparedStatement batch.

Voici ce que je fais maintenant:

private void addToBatch(String sql) throws SQLException{
sttmnt.addBatch(sql);
batchSize++;
if (batchSize == elementsPerExecute){
    executeBatches();
}
}

sttmnt est un membre de classe de type Statement.

Ce que je veux faire, c'est utiliser la méthode preparedStatementsetString(int, String) pour définir des données dynamiques, puis les ajouter au lot.

Malheureusement, je ne comprends pas parfaitement comment cela fonctionne et comment je peux utiliser setString(int, String) pour un SQL spécifique dans le lot OR créer un nouveau preparedStatemnt pour chaque sql que j'ai, puis joignez-les tous à un seul lot.

est-il possible de faire ça? ou est-ce que je manque vraiment quelque chose dans ma compréhension de preparedStatement?

17
Boris C

Lisez le section 6.1.2 de ce document pour des exemples. En gros, vous utilisez le même objet d'instruction et appelez la méthode par lots une fois que tous les espaces réservés sont définis. n autre exemple IBM DB2 qui devrait fonctionner pour toute implémentation JDBC. Depuis le deuxième site:

try {
  connection con.setAutoCommit(false);        
  PreparedStatement prepStmt = con.prepareStatement(    
    "UPDATE DEPT SET MGRNO=? WHERE DEPTNO=?");
  prepStmt.setString(1,mgrnum1);            
  prepStmt.setString(2,deptnum1);
  prepStmt.addBatch();                      

  prepStmt.setString(1,mgrnum2);                        
  prepStmt.setString(2,deptnum2);
  prepStmt.addBatch();
  int [] numUpdates=prepStmt.executeBatch();
  for (int i=0; i < numUpdates.length; i++) {
    if (numUpdates[i] == -2)
      System.out.println("Execution " + i + 
        ": unknown number of rows updated");
    else
      System.out.println("Execution " + i + 
        "successful: " + numUpdates[i] + " rows updated");
  }
  con.commit();
} catch(BatchUpdateException b) {
  // process BatchUpdateException
} 
18
Sanjay T. Sharma

Avec les PreparedStatement, vous avez en quelque sorte des jokers, par exemple

Sring query = "INSERT INTO users (id, user_name, password) VALUES(?,?,?)";
PreparedStatement statement = connection.preparedStatement(query);
for(User user: userList){
    statement.setString(1, user.getId()); //1 is the first ? (1 based counting)
    statement.setString(2, user.getUserName());
    statement.setString(3, user.getPassword()); 
    statement.addBatch();
}

Cela créera 1 PreparedStatement avec la requête ci-dessus. Vous pouvez parcourir la liste lorsque vous souhaitez insérer ou quelles que soient vos intentions. Quand tu veux t'exécuter,

statement.executeBatch();
statement.clearBatch(); //If you want to add more, 
//(so you don't do the same thing twice)
6
RMT

J'ajoute ici une réponse supplémentaire spécifiquement pour MySQL.

J'ai trouvé que le temps nécessaire pour faire un lot d'inserts était similaire à la durée pour faire des insertions individuelles, même avec la transaction unique autour du lot.

J'ai ajouté le paramètre rewriteBatchedStatements=true à mon URL jdbc, et j'ai vu une amélioration spectaculaire - dans mon cas, un lot de 200 insertions est passé de 125 msec. sans le paramètre à environ 10 à 15 msec. avec le paramètre.

Voir MySQL et JDBC avec rewriteBatchedStatements = true

5
GreyBeardedGeek