2017-12-27 17 views
1

私は古い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()ステートメントを実行する前の画像、右側の画像はこのステートメントの直後です。

Screenshot of runtime values

あなたが見ることができるように、私の文字列パラメータを含む配列は今だけ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でマークされた質問から重複ではありません

は、このマークを撤回してください。

+0

[Javaプリペアドステートメントの挿入にtablename変数を使用する方法](https://stackoverflow.com/questions/11312155/how-to-use-a-tablename-variable-for-a-java-prepared -statement-insert) – AxelH

+0

プリペアドステートメントは、値が設定される前に解析され、最適化されるためです。これが_PS_がより速い理由です。クエリは一度解析され、値は後で簡単に提案されるので、DBMSは以前に受け取った最適化されたクエリで何をするべきでないかを判断します。この解決策は、実行可能なことを見るために 'bean.tableName'がどこから来るかによって異なります。 – AxelH

+0

この最初のリンクは面白い情報を持っています:table-nameはpreparedStatementでパラメータ化できません!私はこの修正を試してみるつもりです。 – Heratom

答えて

1

この問題は、私が同じプログラムで持っていた別の問題にリンクしています。 ディスカッションおよび解決策はhereです。

要約すると、preparedStatementはテーブルの名前をパラメータとして使用することはできず、複数の値をパラメータ内に配置することはできません。文字列と整数(および日付)をdifferenciatingせず、見ての通り

String sql = "INSERT INTO (?) VALUES (?)" 
preparedStatement ps = connection.prepareStatement(sql); 
ps.setString(1, "myTableName"); 
ps.setString(2, "'Value1', 'Value2', 3"); 

が、私は1つとして渡すことが3つの引数を望んでいた:

は、私の場合は例えば、私はこのような何かをしようとしました。

のPreparedStatementを扱うことができる唯一の形式は次のとおりです。

String sql = "INSERT INTO " + tableName + " VALUES (?, ?, ?)"; 

実行時前にパラメータの数がわからない場合は、実行時にクエリを構築する必要があります。例は上のリンクで与えられます。

関連する問題