はじめに
こんにちは。
スッキリわかるJava入門 実践編の学習を進めています。
この学習記録を備忘録として残しながら、自身の理解を深めたいと思っています。
今回は第2部「外部資源へのアクセス」/ 第9章「データベースアクセス」について学びました。
データベースは、ファイルにはない検索性能・並列実行・トランザクション制御を備えており、JDBCを使うとJavaからSQLで操作できます。
この記事が、同じくJavaの学習をしている人にとっても参考になりましたら幸いです。
参考書籍について
- 書籍名:スッキリわかるJava入門 実践編
- 著者:中山清喬
- 出版社:インプレス
目次
1. 本章の要点
データベースとは
データベースとは、大量のデータを効率よく管理・検索するための仕組みです。
特徴
ファイルと比べて、検索性能が高く、複数のアプリケーションから同時に扱える(並列実行)ほか、データの整合性を保つトランザクション制御を備えています。
代表的なデータベース製品
- MySQL:オープンソースで広く使われているRDBMS
- PostgreSQL:高機能で信頼性の高いオープンソースのRDBMS
- Oracle Database:大規模システム向けの商用RDBMS
データベースの基本操作
リレーショナルデータベース(RDB)は、データを表形式で管理し、SQLという専用言語で操作します。
SQLでは、次の4つの基本操作を行えます。
- SELECT:データの検索
- INSERT:データの挿入
- UPDATE:データの更新
- DELETE:データの削除
SELECT name, job FROM heroes WHERE hp > 50;
INSERT INTO heroes (name, job, hp) VALUES ('ミナト', '戦士', 100);
UPDATE heroes SET hp = 80 WHERE name = 'ミナト';
DELETE FROM heroes WHERE name = 'アサカ';
データベースの接続と切断
JavaからデータベースにアクセスするにはJDBC(Java Database Connectivity)というAPIを使います。
利用するDBMSのドライバ(JARファイル)をクラスパスに通しておく必要があります。
DriverManagerでConnectionを取得し、使い終わったら切断します。
import java.sql.*;
public class ConnectionExample {
public static void main(String[] args) throws SQLException {
String url = "jdbc:mysql://localhost:3306/game";
String user = "root";
String password = "password";
// try-with-resourcesで接続を自動的に切断する
try (Connection con = DriverManager.getConnection(url, user, password)) {
System.out.println("接続に成功しました");
}
}
}
// 出力例:
// 接続に成功しました
更新系SQL文の送信
INSERT・UPDATE・DELETEなどのデータを変更するSQL文は、PreparedStatementを使って送信します。
「?」の部分にパラメータを設定することで、SQL文を安全に組み立てられます。
import java.sql.*;
public class InsertExample {
public static void main(String[] args) throws SQLException {
String url = "jdbc:mysql://localhost:3306/game";
try (Connection con = DriverManager.getConnection(url, "root", "password");
PreparedStatement ps = con.prepareStatement(
"INSERT INTO heroes (name, job, hp) VALUES (?, ?, ?)")) {
ps.setString(1, "ミナト");
ps.setString(2, "戦士");
ps.setInt(3, 100);
// 更新された行数が返される
int count = ps.executeUpdate();
System.out.println("追加された行数:" + count);
}
}
}
// 出力例:
// 追加された行数:1
PreparedStatementを使う理由
パラメータを文字列連結でSQL文に埋め込むと、SQLインジェクションの脆弱性につながります。
PreparedStatementの「?」にパラメータを設定する方法を使えば、この問題を防げます。
検索系SQL文の送信
SELECTなどの検索系SQL文は、executeQueryメソッドで送信し、結果をResultSetとして受け取ります。
import java.sql.*;
public class SelectExample {
public static void main(String[] args) throws SQLException {
String url = "jdbc:mysql://localhost:3306/game";
try (Connection con = DriverManager.getConnection(url, "root", "password");
PreparedStatement ps = con.prepareStatement(
"SELECT name, job FROM heroes WHERE hp > ?")) {
ps.setInt(1, 50);
try (ResultSet rs = ps.executeQuery()) {
while (rs.next()) {
System.out.println(rs.getString("name") + ":" + rs.getString("job"));
}
}
}
}
}
// 出力例:
// ミナト:戦士
// アサカ:魔法使い
JavaとDBのデータ型
JavaのDate系の型とDBの日時型は対応づけが必要で、TIMESTAMP型の列にはjava.sql.Timestampを使います。
- 書き込み:
ps.setTimestamp(位置, Timestamp)でパラメータに日時を指定する - 読み込み:
rs.getTimestamp("列名")で結果表から日時を取り出す - 注意:java.util.Dateとjava.sql.Dateは、まったく別のクラスとして扱う
import java.sql.*;
public class TimestampExample {
public static void main(String[] args) throws SQLException {
String url = "jdbc:mysql://localhost:3306/game";
try (Connection con = DriverManager.getConnection(url, "root", "password")) {
// 書き込み:現在時刻をTIMESTAMP列に保存
try (PreparedStatement ps = con.prepareStatement(
"INSERT INTO battle_log (hero_name, occurred_at) VALUES (?, ?)")) {
ps.setString(1, "ミナト");
ps.setTimestamp(2, new Timestamp(System.currentTimeMillis()));
ps.executeUpdate();
}
// 読み込み:TIMESTAMP列から日時を取り出す
try (PreparedStatement ps = con.prepareStatement(
"SELECT occurred_at FROM battle_log WHERE hero_name = ?")) {
ps.setString(1, "ミナト");
try (ResultSet rs = ps.executeQuery()) {
while (rs.next()) {
Timestamp ts = rs.getTimestamp("occurred_at");
System.out.println("発生日時:" + ts);
}
}
}
}
}
}
// 出力例:
// 発生日時:2026-11-01 10:30:45.123
トランザクション処理
トランザクションとは、複数のSQL文をひとまとまりの処理として扱う仕組みです。途中で失敗した場合は、すべての変更を取り消せます。
import java.sql.*;
public class TransactionExample {
public static void main(String[] args) throws SQLException {
String url = "jdbc:mysql://localhost:3306/game";
try (Connection con = DriverManager.getConnection(url, "root", "password")) {
con.setAutoCommit(false); // 自動コミットを無効化
try (PreparedStatement ps = con.prepareStatement(
"UPDATE heroes SET hp = hp - ? WHERE name = ?")) {
ps.setInt(1, 30);
ps.setString(2, "ミナト");
ps.executeUpdate();
ps.setInt(1, 30);
ps.setString(2, "アサカ");
ps.executeUpdate();
con.commit(); // 両方成功したら確定
System.out.println("コミットしました");
} catch (SQLException e) {
con.rollback(); // 失敗したら両方取り消す
System.out.println("ロールバックしました");
throw e;
}
}
}
}
// 出力例:
// コミットしました
2. 自分なりの解釈
- データベースはファイルより検索や並列処理に優れ、トランザクションでデータの整合性も保てるため、用途に応じて使い分けることが大切。
- PreparedStatementで「?」にパラメータを設定する方法は、SQLインジェクションを防ぐために必須。
最後まで見ていただきありがとうございました。
次回は、第3部 / 第10章「基本的な開発ツール」について書く予定です。