web-dev-qa-db-ja.com

SELECTクエリにPreparedStatement.addBatch()を使用できますか?

1つの入力が異なる100個のSELECTクエリがあるとします。値にはPreparedStatementを使用できます。

私がWeb上で見るすべてのドキュメントは、バッチの挿入/更新/削除に関するものです。 select文に使用されるバッチを見たことがありません。

これはできますか?もしそうなら、以下のサンプルコードのときに私を助けてください。

これは "IN"句を使用して実行できると思いますが、バッチ処理されたselectステートメントを使用したいと思います。

サンプルコード:

 public void run(Connection db_conn、List value_list){
 String sql = "SELECT * FROM DATA_TABLE WHERE ATTR =?"; 
 PreparedStatement pstmt = db_conn.prepareStatement(sql); 
 for(String value:value_list){
 pstmt.clearParameters(); 
 pstmt.setObject(1、value); 
 pstmt.addBatch(); 
} 
 //ここで何を呼び出しますか?
 int [] result_array = pstmt.executeBatch()
 while(pstmt.getMoreResults()){
 ResultSet result_set = pstmt.getResultSet(); 
 //ここで機能します
} 
} 

これは運転者に依存する行動かもしれないと思います。 JDBCドライバーを使用してIBM AS/400 DB2データベースに対するクエリを書いています。

23
kevinarpe

the Javaチュートリアル を参照してください:

このリストには、行を更新、挿入、または削除するためのステートメントを含めることができます。また、CREATE TABLEやDROP TABLEなどのDDLステートメントを含めることもできます。ただし、SELECTステートメントなど、ResultSetオブジェクトを生成するステートメントを含めることはできません。つまり、リストには、更新カウントを生成するステートメントのみを含めることができます。

作成時にStatementオブジェクトに関連付けられているリストは、最初は空です。メソッドaddBatchを使用して、このリストにSQLコマンドを追加できます。

48
user207421

JDBCはバッチ化されたSELECTクエリの作成を許可しません。これは、私の考えでは、特に準備されたステートメントではIN (...)のように可変数の引数を指定できないためです句。

JavaRanchの記事F.Jへのリンクは、一連の固定サイズのクエリを作成してその結果を結合することでバッチ処理をシミュレートすることを提案しています。これは、面倒で次善の修正のようです。ここで、手動で複数のクエリを作成して処理し、データベースを複数回ヒットする必要があります。手動で定義されたバッチ用に選択された数が不十分である場合、単純なクエリに答えるためだけにデータベースを何度もヒットする可能性があります。

代わりに、必要なフィールド数でPreparedStatementオブジェクトを動的に構築することにしました。これは、手動のバッチ処理よりも多くのPreparedStatementsを作成する可能性があることを意味しますが、データベースにアクセスする頻度を制限し、実装を簡略化します。どちらも重要な問題と見なしています。

/**
 * Use this method to create batch-able queries, e.g:
 * "SELECT * FROM t WHERE x IN (?, ?, ?, ?)"
 * Can be built as:
 * "SELECT * FROM t where x IN ("+getLineOfQs(4)+")"
 */
public static String getLineOfQs(int num) {
  // Joiner and Iterables from the Guava library
  return Joiner.on(", ").join(Iterables.limit(Iterables.cycle("?"), num));
}

/**
 * Gets the set of IDs associated with a given list of words
 */
public Set<Integer> find(Connection conn, List<String> words)
    throws SQLException {
  Set<Integer> result = new HashSet<>();
  try(PreparedStatement ps = conn.prepareStatement(
      "SELECT id FROM my_table WHERE Word IN ("+
      getLineOfQs(words.size())+")")) {
    for(int i = 0; i < words.size(); i++) {
      ps.setString(i+1, words.get(i));
    }

    try (ResultSet rs = ps.executeQuery()) {
      while(rs.next()) {
        result.add(rs.getInt("id"));
      }
    }
  }
  return result;
}

これはコードを書くのにそれほど苦痛ではなく、PreparedStatementを使用する安全性を提供し、不要なデータベースヒットを回避します。

10
dimo414

他の回答で指摘されているように、JDBCバッチ更新はSELECTクエリに対して機能しないか、少なくともそのために使用するためのものではありません。

ただし、質問ではDB2がRDBMSとして言及されているため、このデータベースの公式ドライバーが実際にdoesこの機能を使用してDB2PreparedStatement#executeDB2QueryBatch()(詳細は documentation を参照)。この機能を備えた他のJDBCドライバーについては知りません。

3
knutwannheden

AddBatch()は「削除」/「挿入」/「更新」ステートメント用であり、「選択」ステートメント用ではありません。

3
user963666