JDBCの要点
内容の確認日: 2026-10-04
この分野では、Java からデータベースを操作する標準の API である JDBC (java.sql パッケージ) の使い方が問われます。「どのメソッドが何を返すか」「インデックスは 0 と 1 のどちらから始まるか」「カーソルは最初どこにあるか」といった細かい仕様が中心です。
出題項目は「DriverManager および DataSource を使用したデータベースへの接続」「Statement および PreparedStatement を使用したデータベースの CRUD 操作」「CallableStatement を使用したデータベースの操作」の 3 つです。データベースのドライバは JDK に含まれていないので、この記事のコード例は、実行できるものを除いて流れを示すためのものです。
データベースへの接続
データベースへの接続は Connection で表します。DriverManager.getConnection に JDBC URL を渡して取得します。JDBC URL は jdbc:サブプロトコル:サブネーム の形で、必ず jdbc: で始まります (例: jdbc:mysql://localhost:3306/shop、jdbc:postgresql://localhost/shop)。
getConnection には、(URL)・(URL, ユーザー名, パスワード)・(URL, Properties) の 3 つのオーバーロードがあります。JDBC 4.0 以降は、クラスパスに置いたドライバが自動で登録されるので、Class.forName("ドライバのクラス名") でドライバを読み込む必要はありません。
getConnection をはじめ、JDBC のほとんどのメソッドはチェック例外の SQLException を投げます。URL に合うドライバが見つからない場合も SQLException です。
import java.sql.Connection;import java.sql.DriverManager;import java.sql.SQLException;public class Main { public static void main(String[] args) { try (Connection con = DriverManager.getConnection("jdbc:nodriver:shop")) { System.out.println("接続できた"); } catch (SQLException e) { System.out.println(e.getClass().getSimpleName()); } }}java Main SQLException
アプリケーション・サーバーなどでは、DriverManager の代わりに DataSource から getConnection() で接続を取得するのが一般的です。DataSource を使うと、接続先の設定をコードから切り離したり、コネクション・プールで接続を再利用したりできます。
Connection・Statement・ResultSet はどれも AutoCloseable なので、try-with-resources で確実に閉じます。
SQL の実行: Statement と PreparedStatement
SQL は Statement か PreparedStatement で実行します。実行するメソッドと戻り値は次のとおりです。
・executeQuery(SQL): SELECT 文を実行し、結果を ResultSet で返す
・executeUpdate(SQL): INSERT・UPDATE・DELETE などを実行し、影響を受けた行の数 (int) を返す
・execute(SQL): どんな SQL でも実行できる。結果が ResultSet なら true、更新数なら false を返す (結果は getResultSet()・getUpdateCount() で取り出す)
PreparedStatement は、SQL の値の部分を ? (プレースホルダ) にして事前に準備し、値は setInt・setString などで後から設定します。プレースホルダの番号は 1 から数えます。値は SQL の構文として解釈されないので、SQL インジェクションを防げます。同じ SQL を値を変えて何度も実行するのにも向いています。
String sql = "UPDATE item SET price = ? WHERE price < ?";try (Connection con = DriverManager.getConnection(url, user, password); PreparedStatement ps = con.prepareStatement(sql)) { ps.setInt(1, 500); // 1 つ目の ? (新しい価格) ps.setInt(2, 400); // 2 つ目の ? (条件) int count = ps.executeUpdate(); System.out.println(count + " 件更新しました");}ResultSet の読み取り
executeQuery が返した直後の ResultSet のカーソルは、最初の行の「前」にあります。next() を呼ぶと次の行に進み、行があれば true、なければ false を返します。そのため、while (rs.next()) の形で 1 行ずつ読みます。最初に next() を呼ばずに値を読むと SQLException です。
列の値は getInt・getString などで、列番号 (1 から) か列名を指定して読みます。
try (PreparedStatement ps = con.prepareStatement("SELECT id, name FROM item WHERE price >= ?")) { ps.setInt(1, 300); try (ResultSet rs = ps.executeQuery()) { while (rs.next()) { System.out.println(rs.getInt(1) + ": " + rs.getString("name")); } }}引数なしの createStatement() で作った Statement の ResultSet は TYPE_FORWARD_ONLY で、カーソルは前にしか進めません。createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY) のように指定すると、previous()・absolute(n)・last() などで自由に移動できます。また、Statement を閉じたり、同じ Statement で次の SQL を実行したりすると、それまでの ResultSet は自動的に閉じられます。
トランザクション
Connection は既定で自動コミットが有効で、SQL を実行するたびに変更が確定します。複数の SQL をまとめて 1 つの処理 (トランザクション) にするには、setAutoCommit(false) で自動コミットを止め、最後に commit() で確定するか、途中で失敗したら rollback() で取り消します。
con.setAutoCommit(false);try (PreparedStatement withdraw = con.prepareStatement("UPDATE account SET balance = balance - ? WHERE id = ?"); PreparedStatement deposit = con.prepareStatement("UPDATE account SET balance = balance + ? WHERE id = ?")) { withdraw.setInt(1, 1000); withdraw.setInt(2, 1); withdraw.executeUpdate(); deposit.setInt(1, 1000); deposit.setInt(2, 2); deposit.executeUpdate(); con.commit(); // 2 つの更新をまとめて確定} catch (SQLException e) { con.rollback(); // どちらかが失敗したら両方取り消す}setSavepoint() で途中にセーブポイントを作ると、rollback(セーブポイント) でそこまでだけを取り消すこともできます。
CallableStatement によるストアド・プロシージャの呼び出し
データベースに登録したストアド・プロシージャは、Connection の prepareCall で作った CallableStatement で呼び出します。SQL は {call プロシージャ名(?, ?)} の形で書きます。CallableStatement は PreparedStatement のサブインタフェースなので、setXxx や execute・executeQuery もそのまま使えます。
プロシージャが値を返す OUT パラメータは、実行する前に registerOutParameter(番号, java.sql.Types の型) で登録し、実行した後に getXxx(番号) で取り出します。
try (CallableStatement cs = con.prepareCall("{call count_items(?, ?)}")) { cs.setInt(1, 300); // IN パラメータ cs.registerOutParameter(2, Types.INTEGER); // OUT パラメータを登録 cs.execute(); System.out.println(cs.getInt(2)); // 実行後に取り出す}試験でよくある引っかけ
JDBC URL の形式
JDBC URL は必ず
jdbc:で始まります。mysql://...のようにjdbc:がないと、合うドライバが見つからずSQLExceptionです。executeUpdateの戻り値executeUpdateが返すのは、影響を受けた行の数 (int) です。ResultSetは返しません。executeの戻り値executeは、結果がResultSetならtrue、更新数ならfalseを返します。番号は
1からプレースホルダの番号と、
ResultSetの列番号は、どちらも1から数えます。カーソルの初期位置
ResultSetのカーソルは最初の行の前にあります。next()を呼ばずにgetXxxを呼ぶとSQLExceptionです。自動コミット
既定では SQL ごとに自動でコミットされます。まとめて取り消したいなら
setAutoCommit(false)にします。
問題で確認する
この分野の問題を、解説つきで読めます (登録不要)。
出典・参考
- Oracle University 日本「Java SE 17 Programmer II (1Z0-826-JPN) 試験」
- The Java Tutorials「JDBC Database Access」
- Java SE 17 API ドキュメント「java.sql」
コード例は、試験の対象バージョンで実際にコンパイル・実行して結果を確認しています。