QA@IT

複数SQL文に対応するPreparedStatementの効率的なバッチ実行の方法

16231 PV

単一のSQL文を、PreparedStatementを使用して繰り返し実行するには、addBatch()、executeBatch()を利用することで、効率化が可能です。

PreparedStatement statement = connection.createStatement("insert into A values (?)");
for (Iterator<?> it = items.iterator(); items.hasNext();) {
  statement.setObject(1, it.next());
  statement.addBatch();
}
statement.executeBatch();

PreparedStatementのインスタンスは、パラメーター化されたSQL文1つごとに1つ作成する必要があるため、最後のexecuteBatch()は、SQL文1つごとに実行する必要があります。

実際の用途では、以下のような構造にしようとしています。

PreparedStatement statementA = connection.createStatement("insert into A values (?)");
PreparedStatement statementB = connection.createStatement("insert into B values (?)");
// さらに多数存在する
for (Iterator<?> it = items.iterator(); items.hasNext();) {
  Item item = it.next();
  statementA.setObject(1, item.getA());
  statementA.executeUpdate();
  statementB.setObject(1, item.getB());
  statementB.executeUpdate();
  // さらに多数存在する
  connection.commit();
}

現状では、commitは、要件の都合上必須なため、itemsの要素数 × パラメータ化されたSQL文の個数 回、executeUpdate()を実行しなくてはなりません。
SQLをパラメーター化せず、Java.sql.statement.addBatch(sql)を利用する方法はありますが、DBサーバーのステートメントキャッシュを食いつぶすため、現実的ではありませんし、脆弱性の原因になりやすく危険です。
パラメーター化されたSQL文が複数ある場合、executeUpdate()を、複数のSQL文に対して一括して行う方法は存在しないでしょうか?

回答

現状で問題としているのはexecuteupdate連発する事で遅くなりそうという心配ですか?
実際試して遅かったんでしょうか?

insertを複数もつストアド作成してCallableStatementを使えば呼び出し回数は抑えられそうですどうでしょうか。パラメータもバインドです。

編集 履歴 (0)

両方食い散らかすことには代わりがないよ。前者(Bach)はJavaが散らかす。後者(Update)はデーターベースが食い散らかす。

OracleやMySQLなら LOAD DATA 句等はどうでしょう。

編集 履歴 (1)
ウォッチ

この質問への回答やコメントをメールでお知らせします。