私は古いstrutsアプリケーションで作業していますが、私は一度に何千もの行を追加する可能性があるため、Javaバッチでデータベースにデータを保存する必要があります。preparedStatement.addBatch()はnullパラメータを追加します
したがって、私はこの種のコードを使用します。
Connection c = null;
PreparedStatement batch = null, truncate=null;
String sql = "INSERT INTO ? VALUES (?)";
try {
c = getConnection();
c.setAutoCommit(false);
batch = c.prepareStatement(sql);
for (ClassContainingData bean : values) {
batch.setString(1, bean.getTableName());
batch.setString(2, bean.getAllFieldsValues());
batch.addBatch();
}
int[] resultats = batch.executeBatch();
for(int res : resultats) {
if(res == PreparedStatement.EXECUTE_FAILED) {
batch.close();
c.close();
throw new SQLException("L'ajout des valeurs en base de données a échoué pour au moins une valeur.");
}
}
c.commit();
}
catch (BatchUpdateException b) {
throw new ServiceException("Erreur lors de l'exécution du batch", b);
}
catch (SQLException s) {
throw new ServiceException("Impossible de sauvegarder les beans en base.", s);
}
finally {
getManager().close(batch);
freeConnection(c);
}
私はそのことについて申し訳ありませんフランスの会社で働く原因エラーメッセージは、フランス語です。
このコードは非常に基本的です。私はこことウェブで見つかったすべての例に触発されていますが、私には情報が見つからないようなあいまいなバグがあります。
私がそのまま実行すると、私は例外を取得
CAUSE : java.sql.BatchUpdateException: ORA-00903: invalid table name.
これが私のデータに誤りを指摘するので、私はダブルチェックが、私の入力は大丈夫に見えました。
私はpreparedStatement
の実行時の値を見るためにEclipseデバッガを使いましたが、addBatch()
は、preparedStatement
に空のパラメータセットを追加しました!
ランタイム値のスクリーンショットは次のとおりです。左側の画像はaddBatch()
ステートメントを実行する前の画像、右側の画像はこのステートメントの直後です。
あなたが見ることができるように、私の文字列パラメータを含む配列は今だけnull
値を含む第2の行を、保持します。
データ上の注意:
- それがSQL文の2つのパラメータがあるだけで1行
- 保持する必要がありますので、これは、forループの最初の繰り返しだった:テーブル名、
TABLE_NAME
などをし、挿入する値のフォーマット済みリスト。'Here', 'are', 'values'
など。
1行入力でも15行入力でも問題はありますが(何千もの行について話しましたが、これまでテスト段階でした)
ここで何が問題になるのでしょうか?私はaddBatch()
ステートメントを悪用したとは思わない、むしろ不適切なデータを渡していると思う。
EDIT:
私はパラメータからTABLE_NAMEを撤回し、SQLコマンドが ようになりましたが+ TABLE_NAME + "のINSERT INTO" "VALUES(?)"
これは、別のエラーにつながりました、それは問題を解決しませんでした!
実際、table_nameは正しくなりましたが、[null]行はまだバッチに追加されています。したがって、 「:ORA-00947:java.sql.BatchUpdateExceptionない十分な値を」スローバッチ内の空の値がある私の質問は、AlexHでマークされた質問から重複ではありません
は、このマークを撤回してください。
[Javaプリペアドステートメントの挿入にtablename変数を使用する方法](https://stackoverflow.com/questions/11312155/how-to-use-a-tablename-variable-for-a-java-prepared -statement-insert) – AxelH
プリペアドステートメントは、値が設定される前に解析され、最適化されるためです。これが_PS_がより速い理由です。クエリは一度解析され、値は後で簡単に提案されるので、DBMSは以前に受け取った最適化されたクエリで何をするべきでないかを判断します。この解決策は、実行可能なことを見るために 'bean.tableName'がどこから来るかによって異なります。 – AxelH
この最初のリンクは面白い情報を持っています:table-nameはpreparedStatementでパラメータ化できません!私はこの修正を試してみるつもりです。 – Heratom