この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
はじめに
前回の「JavaからMySQLに接続して登録する」ではSQL文を1つ1つコミットしていましたが、今回は複数のSQL文の登録とトランザクション処理を紹介します。 トランザクション処理を行うと、複数のSQL文の内の1つ以上でエラーが発生した場合に、その全ての処理を無かった事にしてくれます。
テーブル
こちらに登録します。
コード
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class ConnectionClass {
static final String URL = "jdbc:mysql://localhost/cm";
static final String USERNAME = "user";
static final String PASSWORD = "pass";
public static void main(String[] args) {
String sql = "INSERT INTO music VALUES (?, ?, ?, ?);";
String[][] list = {
{"1", "Sam Smith", "Stay With Me", "2015"},
{"2", "Kanye West", "Gold Digger", "2005"},
{"3", "Roni Size", "It's A Jazz Thing", "1994"},
{"4", "Prince", "Kiss", "1988"},
{"5", "Led Zeppelin", "When The Levee Breaks", "1971"}
};
try ( Connection connection = DriverManager.getConnection(URL,USERNAME,PASSWORD);
PreparedStatement statement = connection.prepareStatement(sql); ) {
connection.setAutoCommit(false);
for (int i = 0; i < list.length; i++) {
statement.setInt (1, Integer.valueOf(list[i][0]));
statement.setString(2, list[i][1]);
statement.setString(3, list[i][2]);
statement.setInt (4, Integer.valueOf(list[i][3]));
statement.addBatch();
System.out.println(statement.toString());
}
int[] result = statement.executeBatch();
System.out.println("登録:" + result.length + "件");
try {
connection.commit();
System.out.println("登録成功");
} catch (SQLException e) {
connection.rollback();
System.out.println("登録失敗:ロールバック実行");
e.printStackTrace();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
解説
動的に実行するためのSQL文を定義。 値を当てはめる箇所を "?" と記述します。
String sql = "INSERT INTO music VALUES (?, ?, ?, ?);";
SQL文に当てはめる値の配列。
String[][] list = {
{"1", "Sam Smith", "Stay With Me", "2015"},
{"2", "Kanye West", "Gold Digger", "2005"},
{"3", "Roni Size", "It's A Jazz Thing", "1994"},
{"4", "Prince", "Kiss", "1988"},
{"5", "Led Zeppelin", "When The Levee Breaks", "1971"}
};
SQL文をデータベースに送るオブジェクトを生成。 Statement と違い、ここで仮のSQL文も設定します。
PreparedStatement statement = connection.prepareStatement(sql); ) {
トランザクション処理には複数のSQL文をまとめてコミットを行う必要が有るので、自動コミット機能をオフにします。
connection.setAutoCommit(false);
配列の要素をSQL文に設定します。 setInt() で整数、 setString() で文字列に置き換えられます。 第1引数:”?”の何個目か 第2引数:置き換える値
statement.setInt (1, Integer.valueOf(list[i][0]));
statement.setString(2, list[i][1]);
statement.setString(3, list[i][2]);
statement.setInt (4, Integer.valueOf(list[i][3]));
addBatch() でSQL文をバッチ登録。 確認のために statement.toString() でSQL文などを標準出力します。
statement.addBatch();
System.out.println(statement.toString());
バッチ登録した複数のSQL文をバッチ処理します。 その返り値は int型 の配列で、更新した回数が要素数になります。
int[] result = statement.executeBatch();
データベースに登録します。
connection.commit();
データベースの登録でエラーが発生したらロールバック処理ですべての変更を取り消します。
connection.rollback();
標準出力結果
com.mysql.jdbc.JDBC4PreparedStatement@22d8cfe0: INSERT INTO music VALUES (1, 'Sam Smith', 'Stay With Me', 2015);
com.mysql.jdbc.JDBC4PreparedStatement@22d8cfe0: INSERT INTO music VALUES (2, 'Kanye West', 'Gold Digger', 2005);
com.mysql.jdbc.JDBC4PreparedStatement@22d8cfe0: INSERT INTO music VALUES (3, 'Roni Size', 'It\'s A Jazz Thing', 1994);
com.mysql.jdbc.JDBC4PreparedStatement@22d8cfe0: INSERT INTO music VALUES (4, 'Prince', 'Kiss', 1988);
com.mysql.jdbc.JDBC4PreparedStatement@22d8cfe0: INSERT INTO music VALUES (5, 'Led Zeppelin', 'When The Levee Breaks', 1971);
登録:5件
登録成功
データベースの状態
まとめ
PreparedStatement を使う事は便利なだけではなくSQLインジェクション対策になるので、Statement よりこちらを使う方が良いです。