バッチ処理にデータアクセスコードを記述して、アプリケーションのパフォーマンスを向上させています。PreparedStatementバッチはプレーンテキストと同様に実行されませんステートメント
私は現時点で削除を行っていますが、これは挿入や更新に簡単に適用できます。
私は対処すべき5つのテーブルを持っています。
public void deleteFooList(final int[] fooIds)
throws SQLException {
Connection connection = dataSource.getConnection();
try {
connection.setAutoCommit(false);
PreparedStatement childStatement = connection.prepareStatement(
"DELETE FROM child WHERE fooId = ?");
PreparedStatement otherStatement = connection.prepareStatement(
"DELETE FROM otherfoo WHERE fooId = ?");
PreparedStatement userStatement = connection.prepareStatement(
"DELETE FROM userfoo WHERE fooId = ?");
PreparedStatement modStatement = connection.prepareStatement(
"DELETE FROM modification WHERE fooId = ?");
PreparedStatement fooStatement = connection.prepareStatement(
"DELETE FROM foo WHERE id = ?");
for (int fooId : fooIds) {
childStatement.setInt(1, fooId);
otherStatement.setInt(1, fooId);
userStatement.setInt(1, fooId);
modStatement.setInt(1, fooId);
fooStatement.setInt(1, fooId);
childStatement.addBatch();
otherStatement.addBatch();
userStatement.addBatch();
modStatement.addBatch();
fooStatement.addBatch();
}
executeBatchAndCheckResult(childStatement, fooIds.length);
executeBatchAndCheckResult(otherStatement, fooIds.length);
executeBatchAndCheckResult(userStatement, fooIds.length);
executeBatchAndCheckResult(modStatement, fooIds.length);
executeBatchAndCheckResult(fooStatement, fooIds.length);
connection.commit();
} catch (SQLException e) {
connection.rollback();
throw e;
} finally {
connection.close();
}
}
そして私もこの試みた:完全ではなく、関連性のために含まれ、このヘルパー関数を使用して
public void deleteFooList2(final int[] fooIds)
throws SQLException {
StringBuilder deleteChildSql = new StringBuilder(
"DELETE FROM child WHERE fooId IN (");
StringBuilder deleteOtherSql = new StringBuilder(
"DELETE FROM otherfoo WHERE fooId IN (");
StringBuilder deleteUserSql = new StringBuilder(
"DELETE FROM userfoo WHERE fooId IN (");
StringBuilder deleteModSql = new StringBuilder(
"DELETE FROM modification WHERE fooId IN (");
StringBuilder deleteFooSql = new StringBuilder(
"DELETE FROM foo WHERE id IN (");
Connection connection = childSource.getConnection();
try {
connection.setAutoCommit(false);
Statement statement = connection.createStatement();
for (int x = 0; x < fooIds.length; x++) {
if (x > 0) {
deleteChildSql.append(",");
deleteOtherSql.append(",");
deleteUserSql.append(",");
deleteModSql.append(",");
deleteFooSql.append(",");
}
deleteChildSql.append(fooIds[x]);
deleteOtherSql.append(fooIds[x]);
deleteUserSql.append(fooIds[x]);
deleteModSql.append(fooIds[x]);
deleteFooSql.append(fooIds[x]);
}
deleteChildSql.append(")");
deleteOtherSql.append(")");
deleteUserSql.append(")");
deleteModSql.append(")");
deleteFooSql.append(")");
statement.addBatch(deleteChildSql.toString());
statement.addBatch(deleteOtherSql.toString());
statement.addBatch(deleteUserSql.toString());
statement.addBatch(deleteModSql.toString());
statement.addBatch(deleteFooSql.toString());
executeBatchAndCheckResult(statement, fooIds.length);
connection.commit();
} catch (SQLException e) {
connection.rollback();
throw e;
} finally {
connection.close();
}
を:
これらは私が(ヘルパー関数は、一番下にある)しようとした2つの方法がありprivate void executeBatchAndCheckResult(Statement statement,
int count)
throws SQLException {
int[] results = statement.executeBatch();
if (results == null) {
throw new SQLException(
"Batch update failed to return results!");
}
int total = 0;
for (int result : results) {
total += result;
if (result == Statement.EXECUTE_FAILED) {
String sql = statement.toString();
throw new SQLException(String.format(
"Error executing batch: %s", sql));
}
}
log.info(String.format("Ran batch, statement count %d, row count %d",
results.length, total));
if (results.length != count) {
throw new SQLException(String.format(
"Batch update failed to execute correct count! " +
"(%d instead of %d)", results.length, count));
}
}
私は、普通のStatement
が5 PreparedStatements
よりもずっと速く実行されていることに驚いた。実際、それは見えなかった。 Statement
は、単独で5 PreparedStatements
のいずれかと同じくらい速かった。 PreparedStatement
バッチを間違って実装していますか?
これはStatement
からの高速SQLです:
DELETE FROM foo WHERE id IN (52000,52001,52002,52003,52004,52005,52006,52007,52008,52009,52010)
DELETE FROM modification WHERE fooId IN (52000,52001,52002,52003,52004,52005,52006,52007,52008,52009,52010)
DELETE FROM userfoo WHERE fooId IN (52000,52001,52002,52003,52004,52005,52006,52007,52008,52009,52010)
DELETE FROM otherfoo WHERE fooId IN (52000,52001,52002,52003,52004,52005,52006,52007,52008,52009,52010)
DELETE FROM childfoo WHERE fooId IN (52000,52001,52002,52003,52004,52005,52006,52007,52008,52009,52010)
が、これはPreparedStatements
から遅いSQLです:それは正確に何が起こっているかではありませんので、これはP6Spyからである
DELETE FROM foo WHERE id = 52010
DELETE FROM modification WHERE fooId = 52010
DELETE FROM userfoo WHERE fooId = 52010
DELETE FROM otherfoo WHERE fooId = 52010
DELETE FROM childfoo WHERE fooId = 52010
。 PreparedStatements
からのログは、最後にバッチに追加された項目を表示しているだけで、すべてDELETE
ではありません。
私は上のMySQLのJDBCパラメータrewriteBatchedStatements=true
を持っているので、私は、MySQLのConnector/Jは
DELETE FROM foo WHERE id = 52010 OR id = 52009 OR id = 52008 OR id = 52007 OR id = 52006 OR id = 52005 etc
のような類似したものにバッチを書き換えているか、多分それはないのか?と仮定していますか私は間違って何をすることができますか?
手動で削除するのではなく、カスケードオプション付きの外部キーを使用する必要があります。 –
はデータベースにありますか? JPAフレームワークについて話していますか?もちろん、データベースには – Adam
があります。 –