さまざまな URL からデータを取得し、このデータをデータベースに保存する Java アプリケーションを実装しています。各テーブルには、データを受信する URL の独自のコレクションがあります。これを行うには、テーブルごとに準備済みステートメントを実装し、URL からデータを取得し、データを準備ステートメントにバインドし、テーブルのすべての URL が完了するまでデータをバッチとして追加します。そして、prepare ステートメントで executeBatch を実行します。6 ~ 8 個のテーブルがあり、各テーブルには約 200 行あります。私は各テーブルに対して同じ手順を実行していますが、3〜4個のテーブルを更新した後、executeBacthは次のような例外をスローしています:
java.sql.SQLException: SQL Exception : [Microsoft][ODBC Driver
Manager] Invalid string or buffer length at
sun.jdbc.odbc.JdbcOdbcPreparedStatement.setObject(JdbcOdbcPreparedStatement.java:1438)
at
sun.jdbc.odbc.JdbcOdbcPreparedStatement.setObject(JdbcOdbcPreparedStatement.java:1073)
at
sun.jdbc.odbc.JdbcOdbcPreparedStatement.emulateExecuteBatch(JdbcOdbcPreparedStatement.jjva:2104)
at
sun.jdbc.odbc.JdbcOdbcPreparedStatement.executeBatchUpdate(JdbcOdbcPreparedStatement.java:1782)
at
sun.jdbc.odbc.JdbcOdbcStatement.executeBatch(JdbcOdbcStatement.java:911)
at FaoClient.CFaoTable.InsertFromPartialSource(CFaoTable.java:174)
テーブルのデータをフェッチする順序を変更して同じプログラムをテストしましたが、データ 4 ~ 5 テーブルを挿入した後は常に例外がスローされます。メモリ リークのような状況のように感じますが、私が知っているように、JAVA グラベージ コレクターはこのような状況を決して起こさせません。私はこのJAVAの世界にとても慣れていないので、間違っているかもしれません。レコードを挿入する目的で java.sql.* を使用するコードの一部を貼り付けています。
private boolean BindValueToStmt(PreparedStatement ps, int index, TableCol.ColType type, String ColVal) {
if ((ps == null) || (ColVal == "")) {
return false;
}
try {
switch (type) {
case INTEGERT: {
ps.setInt(index, Integer.parseInt(ColVal));
return true;
}
case STRINGT: {
ps.setString(index, ColVal);
return true;
}
case REALT: {
ps.setFloat(index, Float.parseFloat(ColVal));
return true;
}
case DOUBLET: {
ps.setDouble(index, Double.parseDouble(ColVal));
return true;
}
default:
ps.setNull(index, java.sql.Types.NULL);
}
return true;
} catch (SQLException E) {
System.out.println("Error in Setting the value of the col in table: " + Name + E);
E.printStackTrace();
return false;
}
}
private String CreatePreparedInsertStatement() {
StringBuilder insertStmt = new StringBuilder("insert into " + Name + "(");
String val = " values (";
for (int index = 0; index < Columns.size(); index++) {
TableCol col = Columns.get(index);
if (index != Columns.size() - 1) {
String Stmt = col.GetColName() + ", ";
insertStmt.append(Stmt);
val += "?, ";
} else {
String Stmt = col.GetColName() + ")";
insertStmt.append(Stmt);
val += "?)";
}
}
insertStmt.append(val);
return insertStmt.toString();
}
以下は、実際にデータを挿入しているコードです。
private boolean InsertFromPartialSource(Connection conn, SAXReader reader) {
try {
if (conn == null || reader == null) {
return false;
}
//Some Code not realted to java.sql
conn.setAutoCommit(false);
String strPs= CreatePreparedInsertStatement();
PreparedStatement ps = conn.prepareStatement(strPs);
//Some Code not realted to java.sql
for (int index = 0; index < Columns.size(); index++) {
TableCol col = Columns.get(index);
//Some Code not realted to java.sql
if (!BindValueToStmt(ps, index + 1, col.GetColType(), colVal)) {
ps.setNull(index + 1, TableCol.GetSqlColTypeFrmType(col.GetColType()));
}
}
rowCount++;
System.out.println(rowCount + "rows has been extracted for table \" " + Name);
ps.addBatch();
}
if (rowCount > 0) {
int RecordsUpdated[] = ps.executeBatch();
}
conn.commit();
conn.setAutoCommit(true);
ps.close();
return true;
}
わかりやすくするために、データベースの更新に関連する InsertFromPartialSource 関数の一部のみを貼り付けました。ここで何がうまくいかないのか教えてください。
上記の問題の解決策は次のとおりです 。MySql コネクターまたはドライバーを MySqlJDBC ドライバーに変更します。以下のリンクで見つけることができます: http://dev.mysql.com/downloads/connector/j/5.1.html