JavaプログラムでMariaDBのON DUPLICATE KEY UPDATEを使いこなす
MariaDBでバッチ挿入と重複キー更新を行うJavaプログラム
このチュートリアルでは、Javaを使用してMariaDBデータベースにバッチ挿入を行い、重複するキーが見つかった場合は既存のレコードを更新する方法について説明します。
前提条件
- Java Development Kit (JDK) がインストールされている
- MariaDBデータベースがインストールおよび構成されている
- JDBCドライバ (例:MariaDB Connector/J) をプロジェクトに追加している
手順
接続の確立
import java.sql.*;
public class BatchInsert {
public static void main(String[] args) throws SQLException {
// データベース接続情報
String url = "jdbc:mariadb://localhost:3306/testdb";
String username = "root";
String password = "password";
// データベース接続
try (Connection connection = DriverManager.getConnection(url, username, password)) {
// ステートメントの作成
Statement statement = connection.createStatement();
// バッチ挿入の準備
String sql = "INSERT INTO users (name, email) VALUES (?, ?)";
PreparedStatement preparedStatement = connection.prepareStatement(sql);
// バッチデータの準備
String[][] data = {
{"Alice", "[email protected]"},
{"Bob", "[email protected]"},
{"Charlie", "[email protected]"},
{"Alice", "[email protected]"}, // 重複キー
};
// バッチ処理
for (String[] row : data) {
preparedStatement.setString(1, row[0]);
preparedStatement.setString(2, row[1]);
preparedStatement.addBatch();
}
// バッチ実行
int[] updateCounts = preparedStatement.executeBatch();
// 結果の処理
for (int count : updateCounts) {
if (count == 1) {
System.out.println("新しいレコードが挿入されました");
} else if (count == 2) {
System.out.println("既存のレコードが更新されました");
} else {
System.out.println("処理スキップ");
}
}
// ステートメントと接続のクローズ
statement.close();
}
}
}
コードの説明
- 1-10行: データベース接続情報と接続の確立
- 12-17行: バッチ挿入用のSQLクエリとPreparedStatementの作成
- 19-26行: バッチデータの準備 (名前とメールアドレスの配列)
- 28-34行: バッチ処理 (各行の値をPreparedStatementに設定し、バッチに追加)
- 36行: バッチ実行 (executeBatch() メソッドを使用してバッチ処理を実行)
- 38-44行: 結果の処理 (updateCounts配列を使用して、各行が挿入されたのか更新されたのかを確認)
- 46-49行: ステートメントと接続のクローズ
- このコードは、重複キーが見つかった場合に既存のレコードを更新するように設定されています。
ON DUPLICATE KEY UPDATE
句を使用して、更新する列を指定できます。 - バッチ処理は、一度に複数のレコードを挿入する効率的な方法です。
- エラー処理とロギングを追加することをお勧めします。
import java.sql.*;
public class BatchInsert {
public static void main(String[] args) throws SQLException {
// データベース接続情報
String url = "jdbc:mariadb://localhost:3306/testdb";
String username = "root";
String password = "password";
// データベース接続
try (Connection connection = DriverManager.getConnection(url, username, password)) {
// ステートメントの作成
Statement statement = connection.createStatement();
// バッチ挿入の準備
String sql = "INSERT INTO users (name, email) VALUES (?, ?) ON DUPLICATE KEY UPDATE age = 30";
PreparedStatement preparedStatement = connection.prepareStatement(sql);
// バッチデータの準備
String[][] data = {
{"Alice", "[email protected]"},
{"Bob", "[email protected]"},
{"Charlie", "[email protected]"},
{"Alice", "[email protected]"}, // 重複キー
};
// バッチ処理
for (String[] row : data) {
preparedStatement.setString(1, row[0]);
preparedStatement.setString(2, row[1]);
preparedStatement.addBatch();
}
// バッチ実行
int[] updateCounts = preparedStatement.executeBatch();
// 結果の処理
for (int count : updateCounts) {
if (count == 1) {
System.out.println("新しいレコードが挿入されました");
} else if (count == 2) {
System.out.println("既存のレコードが更新されました");
} else {
System.out.println("処理スキップ");
}
}
// ステートメントと接続のクローズ
statement.close();
}
}
}
ON DUPLICATE KEY UPDATE
句を追加し、age
列を 30 に更新するように設定しました。
説明
ON DUPLICATE KEY UPDATE
句は、INSERTステートメントの一部として使用され、重複するキーが見つかった場合に実行するアクションを指定します。- この例では、
age
列を 30 に更新するように設定しています。他の列も更新するには、この句に追加できます。
ON DUPLICATE KEY UPDATE
句は、既存のレコードを更新する効率的な方法です。
String sql = "INSERT IGNORE INTO users (name, email) VALUES (?, ?)";
バッチ処理をループで実行する
バッチ処理をループで実行することで、各行を個別に挿入し、重複するキーを処理することができます。
for (String[] row : data) {
String sql = "INSERT INTO users (name, email) VALUES (?, ?)";
PreparedStatement preparedStatement = connection.prepareStatement(sql);
preparedStatement.setString(1, row[0]);
preparedStatement.setString(2, row[1]);
try {
preparedStatement.executeUpdate();
System.out.println("新しいレコードが挿入されました");
} catch (SQLException e) {
if (e.getErrorCode() == 1062) { // 重複キーエラー
System.out.println("既存のレコードが更新されました");
// 既存のレコードを更新する処理
} else {
e.printStackTrace();
}
}
preparedStatement.close();
}
ストアドプロシージャを使用する
ストアドプロシージャは、データベースサーバー側で実行されるプログラムです。バッチ挿入と重複キー更新のロジックをストアドプロシージャにカプセル化することで、コードをより簡潔かつ効率的にすることができます。
CREATE PROCEDURE insert_or_update_users(
IN name VARCHAR(255),
IN email VARCHAR(255)
)
BEGIN
INSERT INTO users (name, email) VALUES (name, email)
ON DUPLICATE KEY UPDATE age = 30;
END;
CallableStatement callableStatement = connection.prepareCall("{CALL insert_or_update_users(?, ?)}");
callableStatement.setString(1, "Alice");
callableStatement.setString(2, "[email protected]");
callableStatement.executeUpdate();
それぞれの方法の利点と欠点
方法 | 利点 | 欠点 |
---|---|---|
INSERT ON DUPLICATE KEY UPDATE | シンプルで使いやすい | 重複するキーをどのように処理するかを制御できない |
INSERT IGNORE | 既存のレコードを変更しない | 重複するキーを検出できない |
バッチ処理をループで実行する | 重複するキーを個別に処理できる | コードが冗長になる可能性がある |
ストアドプロシージャ | コードを簡潔かつ効率的にできる | データベースサーバー側で実行する必要がある |
最適な方法は、要件によって異なります。
- シンプルで使いやすい方法が必要な場合は、
INSERT ON DUPLICATE KEY UPDATE
を使用します。 - 既存のレコードを変更したくない場合は、
INSERT IGNORE
を使用します。 - 重複するキーを個別に処理する必要がある場合は、バッチ処理をループで実行します。
- コードを簡潔かつ効率的にしたい場合は、ストアドプロシージャを使用します。
java mysql sql