はじめに
前回、DBの準備編にて作成したDBを用いて
JavaでのDB操作をやってみたいと思います。
前回の記事 → 【Java】MySQLの操作方法(Windows) その1:DB準備編
前提
動作環境は下記の通りです。
項目 | 情報 | 備考 |
---|---|---|
Java バージョン | 14.0.2 | コマンドプロンプトにて java -version で確認 |
MySQL バージョン | 8.0.24 | コマンドプロンプトにて mysql --version で確認 |
C:\>java -version
java version "14.0.2" 2020-07-14
Java(TM) SE Runtime Environment (build 14.0.2+12-46)
Java HotSpot(TM) 64-Bit Server VM (build 14.0.2+12-46, mixed mode, sharing)
C:\>mysql --version
mysql Ver 8.0.24 for Win64 on x86_64 (MySQL Community Server - GPL)
準備
プロジェクトにJDBCドライバーを組み込みます。
・[プロジェクト] -> [プロパティ] を選択
・[Javaのビルド・パス] -> [ライブラリ] -> [外部JARの追加] にて、
C:\Program Files (x86)\MySQL\Connector J 8.0\mysql-connector-java-8.0.24.jar
を選択し、追加します。
(パスは異なる場合がありますので、ご自身の環境に合わせてください。)
実践(Javaでの操作)
1.1 データベースへ接続
まずは、データベースへ接続してみます。
データベースへ接続するために、java.sql.Connectionのインスタンスを取得します。
今回は、DriverManagerのgetConnection()を使用して取得します。
(この他にも、DIコンテナを使用するなど様々な手法が存在する様子・・)
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class SqlConnect {
public static void main(String[] args) {
// データベース接続で使用する情報
final String jdbcId = "root"; // データベースへ接続するユーザ名
final String jdbcPass = "root"; // パスワード
final String jdbcUrl = "jdbc:mysql://localhost:3306/sample"; // ローカル実行なので、localhostを指定。ポートもデフォルトの3306。テスト用のデータベース名のsampleを指定。
// データベースへの接続
try (Connection db = DriverManager.getConnection(jdbcUrl, jdbcId, jdbcPass)) {
System.out.println("接続に成功!!");
} catch (SQLException e) {
System.out.println("接続に失敗:" + e.getMessage());
}
}
}
データベースへの接続が成功すると、コンソールに「接続に成功!!」と表示されます。
なお、データベースへの接続時のclose処理などの後片付けを自動的にしてくれる点では、try-with-resources構文を使用するのが良いらしい。
参考:try-finallyよりもtry-with-resourcesを使おう
しかし、後述のトランザクション処理利用時には、
tryブロックから抜ける際に、catchブロック実行前に自動的にclose処理が動作するため、
明示的なロールバックが記述できないなどのデメリットもある様子・・・
1.2 データベースの検索
データベース内のデータを検索し、取得します。
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class SqlQuery {
public static void main(String[] args) {
// データベース接続用の情報
final String jdbcId = "root";
final String jdbcPass = "root";
final String jdbcUrl = "jdbc:mysql://localhost:3306/sample";
try (Connection db = DriverManager.getConnection(jdbcUrl, jdbcId, jdbcPass)) {
PreparedStatement ps = db.prepareStatement("select * from members where sex = ?");
ps.setString(1, "女");
ResultSet rs = ps.executeQuery();
while (rs.next()) {
System.out.println(rs.getString("name"));
System.out.println(rs.getString("sex"));
System.out.println(rs.getString("age"));
System.out.println("*****************************");
}
} catch (SQLException e) {
System.out.println("接続に失敗:" + e.getMessage());
}
}
}
まずは、
PreparedStatementを使用して、実行したいSQLのひな型を作成します。
後で値を入れたい部分については、?マークを記述します。(パラメータと呼ばれる)
次に、
?部分にsetStringを使用して、具体的な値を入れます。
(今回は文字列を入れるので、setStringを使用)
setString(パラメータ番号, 文字列)の形。(パラメータ番号は1から始まる。?の位置に対応)
準備ができたので、
SQL文をexecuteQueryを使用して、送信します。
結果はResultSetを使用して受け取ります。
最後に、受け取ったResultSetの中身をwhile文を用いて取り出します。
ResultSetのnextメソッドは戻り値をboolean型で返すので、値がある分だけループで取り出せます。
1.3 データベースへのデータ挿入
INSERT文を用いて、データの登録を行います。
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class SqlUpdate {
public static void main(String[] args) {
final String jdbcId = "root";
final String jdbcPass = "root";
final String jdbcUrl = "jdbc:mysql://localhost:3306/sample";
String sql = "INSERT INTO members (id, name, sex, age) VALUES (?, ?, ?, ?)";
try (Connection db = DriverManager.getConnection(jdbcUrl, jdbcId, jdbcPass)) {
PreparedStatement ps = db.prepareStatement(sql);
ps.setString(1, "20210430");
ps.setString(2, "スーパー太郎");
ps.setString(3, "男");
ps.setInt(4, 35);
int result = ps.executeUpdate();
System.out.println(result + "行が追加されました。");
} catch (SQLException e) {
e.printStackTrace();
}
}
}
スーパー太郎さんを追加しています。
PreparedStatementを使用して、SQLのひな型を準備し、
setString、setIntを使用して、具体的な値を入れ込む部分は検索と同じです。
SQLを送信する際のメソッドが、executeUpdateメソッドになっています。
また、戻り値は「データベースで変更された行数」となるので、int型で受けています。
本当に追加されたかは、1.2の検索の条件を変更して実行すれば確認できます。
変更前:ps.setString(1, "女");
変更後:ps.setString(1, "男");
1.4 トランザクション処理
最後にトランザクション処理をやってみます。
なお、トランザクション処理そのものの解説は行いませんので、ググって調べてください。
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class SqlTransact {
public static void main(String[] args) {
// データベース接続用の情報
final String jdbcId = "root";
final String jdbcPass = "root";
final String jdbcUrl = "jdbc:mysql://localhost:3306/sample";
String sql1 = "INSERT INTO members (id, name, sex, age) VALUES (?, ?, ?, ?)";
String sql2 = "INSERT INTO members (id, name, sex, age) VALUES (?, ?, ?, ?)";
try (Connection db = DriverManager.getConnection(jdbcUrl, jdbcId, jdbcPass)) {
// トランザクション処理のため、自動コミットをオフ
db.setAutoCommit(false);
try (PreparedStatement ps1 = db.prepareStatement(sql1) ; PreparedStatement ps2 = db.prepareStatement(sql2)) {
ps1.setString(1, "20210431");
ps1.setString(2, "田中春香");
ps1.setString(3, "女");
ps1.setInt(4, 20);
ps1.executeUpdate();
ps2.setString(1, "20210431");
ps2.setString(2, "鈴木春香");
ps2.setString(3, "女");
ps2.setInt(4, 24);
ps2.executeUpdate();
// データベースへコミット
db.commit();
} catch (SQLException e) {
// データベースをロールバック
db.rollback();
System.out.println("処理エラー:" + e.getMessage());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
トランザクション処理を行うためには、自動コミットをオフにするために
データベース接続に取得したConnection(dbという変数)に対して、
setAutoCommit(false)を実行しています。
そして一連の処理が完了した後に、commit()を呼び出し、コミット処理を実行しています。
なお、途中で処理が失敗した場合には、
処理をキャンセルするために、rollback()を呼び出しています。
今回の例では、idがプライマリキーとなっているにも関わらず、
重複して登録しようとしているので、処理がエラーとなり、誰も追加されません。
(鈴木さんの追加時(ps2のほう)、エラーとなる。)
下記のように変更を行えば、正常に登録がされます。
変更前:ps2.setString(1, "20210431");
変更後:ps2.setString(1, "20210432");
おわりに
Javaを用いて、データベース操作を行ってみました。
今回のやり方以外にも手法が存在するようなので、都度、学習していけたらと思います。