今回は、そのJDBCを使って実際にJavaプログラムからデータベースを操作する方法を、具体的なコードを交えながら見ていこう!
JDBCと聞くと難しそうに感じるかもしれないけど、基本的な流れは決まっているから安心してね。今回はSQLiteというファイルベースの軽量なデータベースを使って説明するよ。これなら特別なサーバーを用意する必要がないから、すぐに試せるはずだ。
JDBC操作の基本的な流れ
JDBCでデータベースを操作する手順は、だいたい以下の4ステップに分けられるんだ。
- JDBCドライバーの読み込み
- データベースへの接続
- SQL文の実行
- データベースとの切断
この流れをしっかり頭に入れておくと、どんなデータベースを扱うときでも応用できるからね!
準備をしよう!
まずは、JDBCドライバーを準備しよう。今回はSQLiteを使うから、SQLite JDBCドライバーをプロジェクトに追加する必要があるよ。Mavenを使っているならpom.xmlに以下を追加すればOKだ。
XML
<dependency>
<groupId>org.xerial</groupId>
<artifactId>sqlite-jdbc</artifactId>
<version>3.45.1.0</version>
</dependency>
Mavenを使っていない場合は、SQLite JDBCの公式ページからjarファイルをダウンロードして、プロジェクトのビルドパスに追加してね。
1. JDBCドライバーの読み込み
昔はClass.forName()を使ってドライバーを明示的に読み込む必要があったんだけど、最近のJDBCドライバーはService Provider Interface (SPI) を使っているので、ほとんどの場合この記述は不要なんだ。でも、もし古いバージョンのドライバーを使う場合や、何か問題が起きた場合は、覚えておくと良いかもしれないね。
Java
// 最近のJDBCドライバーではほとんどの場合不要
// Class.forName("org.sqlite.JDBC");
2. データベースへの接続
データベースに接続するには、DriverManager.getConnection()メソッドを使うよ。このメソッドには、接続するデータベースのURLと、必要であればユーザー名とパスワードを渡すんだ。SQLiteの場合はファイルパスを指定するだけだよ。
Java
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class DbConnectionExample {
public static void main(String[] args) {
String url = "jdbc:sqlite:test.db"; // test.dbというファイルが作成される
try (Connection conn = DriverManager.getConnection(url)) {
System.out.println("データベースに接続しました!");
// ここでデータベース操作を行う
} catch (SQLException e) {
System.err.println("データベース接続エラー: " + e.getMessage());
}
}
}
ここで使っているtry-with-resources文は、Connectionのようなリソースを自動的にクローズしてくれる便利な構文だよ。これを使うと、finallyブロックでclose()を呼び出す手間が省けるし、クローズし忘れによるエラーも防げるから、積極的に使っていこう!
3. SQL文の実行
データベースに接続できたら、次はSQL文を実行してみよう。SQL文を実行するには、主に以下の2つのインターフェースを使うよ。
Statement: 静的なSQL文を実行する場合PreparedStatement: パラメータを含むSQL文を実行する場合(SQLインジェクション対策にもなる!)
今回はPreparedStatementを中心に見ていこう。セキュリティ的にもこちらを使うのがおすすめだよ。
テーブルの作成
まずは、データを格納するテーブルを作ってみよう。Statementを使ってテーブルを作成する例だよ。
Java
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class CreateTableExample {
public static void main(String[] args) {
String url = "jdbc:sqlite:test.db";
try (Connection conn = DriverManager.getConnection(url);
Statement stmt = conn.createStatement()) { // Statementを作成
String sql = "CREATE TABLE IF NOT EXISTS users (" +
"id INTEGER PRIMARY KEY AUTOINCREMENT," +
"name TEXT NOT NULL," +
"age INTEGER)";
stmt.execute(sql); // SQL文を実行
System.out.println("usersテーブルが作成されたか、すでに存在します。");
} catch (SQLException e) {
System.err.println("テーブル作成エラー: " + e.getMessage());
}
}
}
IF NOT EXISTSとつけることで、もしテーブルがすでに存在していたとしてもエラーにならないようにしているんだ。便利だね!
データの挿入(INSERT)
次に、作ったテーブルにデータを挿入してみよう。ここではPreparedStatementの出番だよ!
Java
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class InsertDataExample {
public static void main(String[] args) {
String url = "jdbc:sqlite:test.db";
try (Connection conn = DriverManager.getConnection(url)) {
String sql = "INSERT INTO users (name, age) VALUES (?, ?)";
try (PreparedStatement pstmt = conn.prepareStatement(sql)) {
// 1人目のユーザー
pstmt.setString(1, "田中 太郎"); // 1番目の?に値をセット
pstmt.setInt(2, 30); // 2番目の?に値をセット
pstmt.executeUpdate(); // 実行
System.out.println("田中 太郎のデータを挿入しました。");
// 2人目のユーザー
pstmt.setString(1, "佐藤 花子");
pstmt.setInt(2, 25);
pstmt.executeUpdate();
System.out.println("佐藤 花子のデータを挿入しました。");
}
} catch (SQLException e) {
System.err.println("データ挿入エラー: " + e.getMessage());
}
}
}
?を使うことで、SQL文に直接値を埋め込まずに済むのがPreparedStatementの大きな特徴だよ。これにより、悪意のあるSQLインジェクション攻撃からシステムを守ることができるんだ。それぞれのsetXXX()メソッドで、対応するデータ型の値をセットするよ。
データの取得(SELECT)
データベースにデータが入ったから、今度はそれをJavaプログラムから読み出してみよう!データの取得にはexecuteQuery()メソッドを使うよ。結果はResultSetというオブジェクトで返ってくるんだ。
Java
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class SelectDataExample {
public static void main(String[] args) {
String url = "jdbc:sqlite:test.db";
try (Connection conn = DriverManager.getConnection(url)) {
String sql = "SELECT id, name, age FROM users WHERE age >= ?";
try (PreparedStatement pstmt = conn.prepareStatement(sql)) {
pstmt.setInt(1, 28); // 28歳以上のユーザーを検索
try (ResultSet rs = pstmt.executeQuery()) { // データを取得
while (rs.next()) { // 次の行がある限りループ
int id = rs.getInt("id"); // "id"列のint値を取得
String name = rs.getString("name"); // "name"列のString値を取得
int age = rs.getInt("age"); // "age"列のint値を取得
System.out.println("ID: " + id + ", 名前: " + name + ", 年齢: " + age);
}
}
}
} catch (SQLException e) {
System.err.println("データ取得エラー: " + e.getMessage());
}
}
}
ResultSetは、取得したデータを行ごとに処理するためのカーソルみたいなものだとイメージしてね。rs.next()で次の行に移動して、データがある場合はtrueを返すから、whileループで全ての行を処理できるんだ。各列の値は、getInt(), getString()などのメソッドを使って取得するよ。列名か列のインデックス(1から始まる)で指定できるけど、列名で指定する方が可読性が高いからおすすめだ。
データの更新(UPDATE)
既存のデータを更新してみよう。これもPreparedStatementを使ってexecuteUpdate()メソッドで実行するよ。
Java
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class UpdateDataExample {
public static void main(String[] args) {
String url = "jdbc:sqlite:test.db";
try (Connection conn = DriverManager.getConnection(url)) {
String sql = "UPDATE users SET age = ? WHERE name = ?";
try (PreparedStatement pstmt = conn.prepareStatement(sql)) {
pstmt.setInt(1, 31); // 新しい年齢
pstmt.setString(2, "田中 太郎"); // 更新対象の名前
int rowsAffected = pstmt.executeUpdate(); // 更新された行数を取得
if (rowsAffected > 0) {
System.out.println("田中 太郎の年齢を更新しました。");
} else {
System.out.println("田中 太郎は見つかりませんでした。");
}
}
} catch (SQLException e) {
System.err.println("データ更新エラー: " + e.getMessage());
}
}
}
executeUpdate()は、INSERT、UPDATE、DELETE文の実行に使われるよ。実行された行数を返すから、更新が成功したかどうかの確認にも使えるんだ。
データの削除(DELETE)
最後に、いらないデータを削除してみよう。これもexecuteUpdate()を使うよ。
Java
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class DeleteDataExample {
public static void main(String[] args) {
String url = "jdbc:sqlite:test.db";
try (Connection conn = DriverManager.getConnection(url)) {
String sql = "DELETE FROM users WHERE name = ?";
try (PreparedStatement pstmt = conn.prepareStatement(sql)) {
pstmt.setString(1, "佐藤 花子"); // 削除対象の名前
int rowsAffected = pstmt.executeUpdate();
if (rowsAffected > 0) {
System.out.println("佐藤 花子のデータを削除しました。");
} else {
System.out.println("佐藤 花子は見つかりませんでした。");
}
}
} catch (SQLException e) {
System.err.println("データ削除エラー: " + e.getMessage());
}
}
}
これで、データベースの基本的な操作であるCRUD(Create, Read, Update, Delete)を一通りJavaから実行する方法が分かったね!
4. データベースとの切断
これは超重要なステップだよ!データベースとの接続は、使い終わったら必ず切断する必要があるんだ。もし切断し忘れると、データベースのリソースを圧迫したり、予期せぬエラーの原因になったりするから注意してね。
上で説明したtry-with-resources文を使えば、ConnectionやStatement、ResultSetなどのリソースが自動的にクローズされるから、この心配はほとんどなくなるよ。だから、積極的にtry-with-resourcesを使っていこう!
Java
// try-with-resourcesを使えば自動的にクローズされる
try (Connection conn = DriverManager.getConnection(url);
PreparedStatement pstmt = conn.prepareStatement(sql);
ResultSet rs = pstmt.executeQuery()) {
// ... 処理 ...
} catch (SQLException e) {
// ... エラーハンドリング ...
}
まとめ
今回は、JDBCを使ってJavaからデータベースを操作する基本的な方法を、具体的なコードをたくさん使いながら解説したよ。
- JDBC操作は「ドライバー読み込み」「接続」「SQL実行」「切断」の4ステップ!
try-with-resources文でリソースのクローズ忘れを防ごう!- SQLインジェクション対策として
PreparedStatementを使おう!
これで、君もJavaでデータベースと会話できるようになったはずだ!最初は少し戸惑うかもしれないけど、何度も手を動かしてコードを書いてみることが上達の近道だよ。
もっと詳しく知りたいことや、こんなこともできるの?といった疑問があったら、ぜひコメントで教えてね。


コメント