web-dev-qa-db-ja.com

バッチでのJDBC prepareStatementの使用

Statementsバッチを使用してデータベースにクエリを実行しています。今、いくつかの調査を行っており、代わりにpreparedStatementを使用するようにアプリケーションを書き直したいのですが、preparedStatementバッチにクエリを追加する方法を理解するのに苦労しています。

これは私が今やっていることです:

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

ここで、sttmntStatementタイプのクラスメンバーです。

私がやりたいことは、preparedStatementsetString(int, String)メソッドを使用して動的データを設定し、それをバッチに追加することです。

残念ながら、私はそれがどのように機能するか、バッチで特定のSQLに対してsetString(int, String)をどのように使用できるかを完全に理解していませんOR新しいpreparedStatemntを作成します私が持っているすべてのSQLについて、それらをすべて1つのバッチに結合します。

それを行うことは可能ですか?または、preparedStatementの理解に本当に欠けているものはありますか?

17
Boris C

このドキュメントのセクション6.1.2 の例を参照してください。基本的には、同じステートメントオブジェクトを使用し、すべてのプレースホルダーを設定した後でバッチメソッドを呼び出します。 別のIBM DB2の例 これは、JDBC実装で機能するはずです。 2番目のサイトから:

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

PreparedStatementを使用すると、ワイルドカードを使用できます。たとえば、

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

これにより、上記のクエリを使用して1 PreparedStatementが作成されます。挿入する場合、または意図したとおりにリストをループすることができます。実行したいときは

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

ここでは、MySQLについて特別な答えを追加します。

バッチの周りに単一のトランザクションがある場合でも、挿入のバッチを実行する時間は、個々の挿入を実行する時間の長さに類似していることがわかりました。

パラメータrewriteBatchedStatements=trueをjdbcのurlに追加すると、劇的な改善が見られました。私の場合、200挿入のバッチは125ミリ秒でした。パラメータなしで約10〜15ミリ秒。パラメータ付き。

MySQLおよびJDBC with rewriteBatchedStatements = true を参照してください。

5
GreyBeardedGeek