
サーブレット&JSPの基本|JDBCでデータを取得する
以下が、「JDBCでデータを取得する」として整えた記事本文です。EMPLOYEESテーブルのレコード例は、山田 太郎 30歳、佐藤 花子 27歳に差し替えています。
JavaからSQLを送り、データベースの結果を受け取る。JDBCでEMPLOYEESテーブルの従業員情報を取得しよう
前回までに、H2 Databaseを導入し、studyデータベースを作成しました。
さらに、studyデータベースの中にEMPLOYEESテーブルを作成し、従業員データを追加しました。
ここまでの作業で、H2コンソールからSQLを実行すれば、EMPLOYEESテーブルの中身を確認できる状態になっています。
次に行うのは、Javaプログラムからデータベースに接続し、EMPLOYEESテーブルのデータを取得することです。
Javaプログラムからデータベースを利用するには、JDBCを使います。
JDBCでは、JavaプログラムがDBMSへSQL文を送り、その結果をJava側で受け取ります。
たとえば、EMPLOYEESテーブルからすべての従業員情報を取得したい場合、JavaプログラムはSELECT文を用意し、データベースへ送信します。
DBMSはEMPLOYEESテーブルを検索し、検索結果をJavaプログラムへ返します。
Javaプログラムは、その結果をResultSetとして受け取り、1行ずつデータを取り出して利用します。
この記事では、JDBCプログラムの全体像を確認しながら、H2 DatabaseのEMPLOYEESテーブルから従業員情報を取得して、Eclipseのコンソールビューに表示する方法を学習します。
JDBCプログラムで行うこと
JDBCプログラムでは、Javaプログラムからデータベースへ接続し、SQLを実行します。
今回の目的は、EMPLOYEESテーブルに保存されている全従業員情報を取得して表示することです。
今回取得するEMPLOYEESテーブルのデータ
| ID | NAME | AGE |
|---|---|---|
| EMP001 | 山田 太郎 | 30 |
| EMP002 | 佐藤 花子 | 27 |
このデータを、JavaプログラムからSELECT文で取得します。
実行するSQL文は、次の内容です。
SELECT ID, NAME, AGE FROM EMPLOYEESこのSELECT文を実行すると、EMPLOYEESテーブルのID、NAME、AGE列を取得できます。
JDBCプログラムの基本的な流れ
JDBCプログラムは、いくつかの決まった手順でデータベースを利用します。
最初は少し長く見えますが、流れを押さえると理解しやすくなります。
JDBCでデータを取得する流れ
| 順番 | 処理 | 使う主なクラスやインタフェース |
|---|---|---|
| 1 | JDBCドライバを読み込む | Class.forName |
| 2 | データベースに接続する | DriverManager、Connection |
| 3 | SELECT文を準備する | PreparedStatement |
| 4 | SELECT文を実行する | PreparedStatement |
| 5 | 検索結果を受け取る | ResultSet |
| 6 | ResultSetから値を取り出す | ResultSet |
| 7 | 取得した値を利用する | System.out.printlnなど |
| 8 | 接続を閉じる | try-with-resources |
Javaプログラムからデータベースを使うには、まずH2 Database用のJDBCドライバを読み込みます。
次に、DriverManagerを使ってデータベースへ接続し、Connectionを取得します。
そのConnectionからPreparedStatementを作成し、SQL文を実行します。
SELECT文の結果はResultSetとして返ってくるため、ResultSetから1行ずつ値を取り出します。
図1:JDBCでEMPLOYEESテーブルのデータを取得する流れ

この図から分かること
JDBCでは、Javaプログラムがデータベースへ直接触るのではなく、DBMSにSQL文を送信して処理を依頼します。
JavaプログラムはConnectionでデータベースと接続し、PreparedStatementでSELECT文を送ります。
DBMSはEMPLOYEESテーブルを検索し、その結果をResultSetとしてJavaプログラムへ返します。
JavaプログラムはResultSetから1行ずつ値を取り出し、必要な形で利用します。
JDBCドライバを読み込む
JDBCプログラムでは、最初にJDBCドライバを読み込みます。
H2 Databaseを利用する場合、ドライバクラス名はorg.h2.Driverです。
プログラムでは、次のようにClass.forNameを使って読み込みます。
Class.forName("org.h2.Driver");この処理により、H2 Databaseへ接続するためのJDBCドライバを利用できる状態にします。
ただし、H2のJDBCドライバがWEB-INF/libやクラスパスに正しく配置されていない場合、ClassNotFoundExceptionが発生します。
そのため、JDBCドライバの読み込みはtry文で囲み、失敗した場合に分かりやすく例外を発生させます。
JDBCドライバ読み込みで確認すること
| 確認項目 | 内容 |
|---|---|
| ドライバクラス名 | org.h2.Driver |
| 必要なJARファイル | h2-x.x.x.jar |
| 配置場所 | 動的Webプロジェクトではsrc/main/webapp/WEB-INF/lib |
| 失敗時の例外 | ClassNotFoundException |
JDBCドライバを読み込めない状態では、後続のデータベース接続処理を行えません。
そのため、ドライバが見つからない場合は、プログラムを続行せずに停止するようにします。
データベースに接続する
JDBCドライバを読み込んだら、次にデータベースへ接続します。
データベースへ接続するには、DriverManager.getConnectionを使います。
H2 Databaseのstudyデータベースへサーバーモードで接続する場合、JDBC URLは次のようになります。
jdbc:h2:tcp://localhost/~/studyユーザー名はsa、パスワードは空文字として接続します。
Connection conn = DriverManager.getConnection(
"jdbc:h2:tcp://localhost/~/study", "sa", "");この処理が成功すると、Javaプログラムとデータベースの接続を表すConnectionインスタンスを取得できます。
接続情報
| 項目 | 値 |
|---|---|
| JDBC URL | jdbc:h2:tcp://localhost/~/study |
| ユーザー名 | sa |
| パスワード | 空文字 |
| 接続先 | H2 Databaseのstudyデータベース |
Connectionは、Javaプログラムとデータベースをつなぐ接続です。
SQLを送るには、このConnectionが必要になります。
try-with-resourcesで接続を自動的に閉じる
データベース接続は、使い終わったら閉じる必要があります。
接続を閉じ忘れると、不要な接続が残り、データベースの利用に影響することがあります。
Javaでは、try-with-resourcesを使うと、tryブロックの処理が終わったときに自動的にリソースを閉じられます。
try (Connection conn = DriverManager.getConnection(
"jdbc:h2:tcp://localhost/~/study", "sa", "")) {
// データベース処理を書く
} catch (SQLException e) {
e.printStackTrace();
}このように書くと、tryブロックを抜けるときにConnectionが自動的に閉じられます。
データベース接続の閉じ忘れを防げるため、JDBCプログラムではよく使う書き方です。
SELECT文を準備する
データベースへ接続できたら、次にSQL文を準備します。
今回は、EMPLOYEESテーブルからID、NAME、AGEを取得します。
String sql = "SELECT ID, NAME, AGE FROM EMPLOYEES";
PreparedStatement pStmt = conn.prepareStatement(sql);SQL文はString型の変数sqlに代入します。
その後、ConnectionのprepareStatementメソッドを使って、PreparedStatementを取得します。
PreparedStatementの役割
| 項目 | 内容 |
|---|---|
| 役割 | SQL文をDBMSへ送信する準備をする |
| 作成方法 | conn.prepareStatement(sql) |
| 今回のSQL | SELECT ID, NAME, AGE FROM EMPLOYEES |
| 実行方法 | executeQueryを使う |
PreparedStatementは、SQL文をデータベースに届けるための部品です。
SELECT文を実行するときは、このPreparedStatementからexecuteQueryを呼び出します。
図2:ConnectionとPreparedStatementでSELECT文を届ける

この図から分かること
DriverManager.getConnectionを実行すると、JavaプログラムとデータベースをつなぐConnectionを取得できます。
Connectionは、JavaプログラムとDBMSをつなぐ道路のような役割を持っています。
そのConnectionからPreparedStatementを作成し、SELECT文をDBMSへ送信します。
PreparedStatementは、SQL文を運ぶ車のような役割です。
JDBCプログラムでは、ConnectionとPreparedStatementを組み合わせて、SQLをデータベースへ届けます。
SELECT文を実行してResultSetを取得する
PreparedStatementを作成したら、SELECT文を実行します。
SELECT文を実行するには、executeQueryを使います。
ResultSet rs = pStmt.executeQuery();executeQueryを実行すると、DBMSがEMPLOYEESテーブルを検索します。
検索結果はResultSetとして返されます。
executeQueryの役割
| 項目 | 内容 |
|---|---|
| 実行するSQL | SELECT文 |
| 戻り値 | ResultSet |
| 役割 | 検索結果を受け取る |
| 今回の結果 | EMPLOYEESテーブルの全従業員情報 |
ResultSetには、SELECT文で取得した結果が格納されています。
今回であれば、EMP001の山田 太郎さん、EMP002の佐藤 花子さんの2件が検索結果として入ります。
ResultSetからレコードを取り出す
ResultSetには、検索結果のレコードが格納されています。
ResultSetからデータを取り出すには、nextメソッドを使います。
while (rs.next()) {
// 1行分のデータを取り出す
}rs.nextを実行すると、取り出し対象のレコードが次の行へ進みます。
レコードが存在すればtrueを返します。
存在しなければfalseを返します。
そのため、while文と組み合わせることで、検索結果を1行ずつ処理できます。
ResultSetのnextメソッド
| 戻り値 | 内容 |
|---|---|
| true | 次のレコードが存在する |
| false | 次のレコードが存在しない |
検索結果が2件ある場合、rs.nextは2回trueを返し、3回目でfalseを返します。
そのため、while文の中の処理は2回実行されます。
各列の値を取得する
ResultSetで1行分のレコードを選択したら、そのレコードの各列の値を取り出します。
文字列の列はgetString、整数の列はgetIntで取得します。
String id = rs.getString("ID");
String name = rs.getString("NAME");
int age = rs.getInt("AGE");ID列とNAME列は文字列として取得するため、getStringを使います。
AGE列は整数として取得するため、getIntを使います。
列の値を取得するメソッド
| 取得する列 | データ型 | 使用するメソッド |
|---|---|---|
| ID | 文字列 | getString("ID") |
| NAME | 文字列 | getString("NAME") |
| AGE | 整数 | getInt("AGE") |
列名は、SQLで取得した列名に合わせて指定します。
今回のSQLではID、NAME、AGEを取得しているため、ResultSetでも同じ列名で値を取り出します。
取得したデータを表示する
ResultSetから取り出した値は、Javaプログラムの中で利用できます。
今回は、Eclipseのコンソールビューに表示します。
System.out.println("ID:" + id);
System.out.println("名前:" + name);
System.out.println("年齢:" + age + "\n");このようにして、取得したID、名前、年齢をコンソールに出力します。
JDBCプログラムの学習では、まずコンソールに出力して、データベースから正しく値を取得できているかを確認すると分かりやすいです。
全従業員情報を検索するJDBCプログラムの例
ここでは、EMPLOYEESテーブルから全従業員情報を取得し、コンソールに表示するJDBCプログラムを作成します。
ファイル名: SelectEmployees.java
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class SelectEmployees {
public static void main(String[] args) {
// JDBCドライバを読み込む
try {
Class.forName("org.h2.Driver");
} catch (ClassNotFoundException e) {
throw new IllegalStateException(
"JDBCドライバを読み込めませんでした");
}
// データベースに接続
try (Connection conn = DriverManager.getConnection(
"jdbc:h2:tcp://localhost/~/study", "sa", "")) {
// SELECT文を準備
String sql = "SELECT ID, NAME, AGE FROM EMPLOYEES";
PreparedStatement pStmt = conn.prepareStatement(sql);
// SELECT文を実行し、結果表を取得
ResultSet rs = pStmt.executeQuery();
// 結果表に格納されたレコードの内容を表示
while (rs.next()) {
String id = rs.getString("ID");
String name = rs.getString("NAME");
int age = rs.getInt("AGE");
// 取得したデータを出力
System.out.println("ID:" + id);
System.out.println("名前:" + name);
System.out.println("年齢:" + age + "\n");
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}このプログラムは、デフォルトパッケージに作成する想定です。
H2 Databaseのstudyデータベースへ接続し、EMPLOYEESテーブルからID、NAME、AGEを取得します。
取得した結果はResultSetに格納され、while文で1行ずつ取り出してコンソールに表示します。
SelectEmployees.javaの処理の流れ
SelectEmployees.javaでは、JDBCプログラムに必要な処理を順番に行っています。
SelectEmployees.javaで行っていること
| 順番 | 処理 | 内容 |
|---|---|---|
| 1 | importを書く | JDBCで使うクラスやインタフェースを読み込む |
| 2 | JDBCドライバを読み込む | Class.forNameでorg.h2.Driverを読み込む |
| 3 | データベースに接続する | DriverManager.getConnectionでConnectionを取得する |
| 4 | SELECT文を準備する | SQL文字列を作り、PreparedStatementを取得する |
| 5 | SELECT文を実行する | executeQueryでResultSetを取得する |
| 6 | 検索結果を1行ずつ進める | while文とrs.nextを使う |
| 7 | 各列の値を取得する | getStringやgetIntを使う |
| 8 | 取得した値を表示する | System.out.printlnでコンソールに出力する |
| 9 | 例外を処理する | SQLExceptionをcatchする |
それぞれの処理が、データベースを利用するために必要な手続きです。
最初は長く見えるかもしれませんが、JDBCプログラムではよく使う形です。
importしているクラスやインタフェース
SelectEmployees.javaでは、java.sqlパッケージから必要なクラスやインタフェースをimportしています。
importしているもの
| import | 役割 |
|---|---|
| java.sql.Connection | データベースとの接続を表す |
| java.sql.DriverManager | データベース接続の入口になる |
| java.sql.PreparedStatement | SQL文を実行する |
| java.sql.ResultSet | SELECT文の検索結果を受け取る |
| java.sql.SQLException | データベース処理の例外を扱う |
これらは、Javaプログラムからデータベースを利用するときに必要になる代表的な部品です。
java.sqlパッケージはJava SEの標準APIに含まれているため、追加でダウンロードする必要はありません。
H2 Databaseに接続するためには、これらに加えてH2のJDBCドライバが必要です。
実行方法
SelectEmployees.javaを作成したら、EclipseでJavaアプリケーションとして実行します。
Eclipseでの実行手順
| 手順 | 内容 |
|---|---|
| 1 | SelectEmployees.javaを作成する |
| 2 | H2 Databaseを起動しておく |
| 3 | H2コンソールで組み込みモード接続を開いたままにしていないことを確認する |
| 4 | SelectEmployees.javaを選択する |
| 5 | 右クリックする |
| 6 | 実行を選択する |
| 7 | Javaアプリケーションを選択する |
| 8 | Eclipseのコンソールビューを確認する |
H2 Databaseが起動していない場合、接続できません。
また、組み込みモードでH2コンソールがstudyデータベースに接続したままだと、Javaプログラムから接続できない場合があります。
Javaプログラムから接続する前に、H2コンソール側の接続状態も確認しておきましょう。
実行手順の補足
「SelectEmployees.java」を右クリックして、実行を選択し、Javaアプリケーションを選択します。

実行結果
EMPLOYEESテーブルに山田 太郎さんと佐藤 花子さんのデータが入っている場合、実行するとEclipseのコンソールビューに次のように表示されます。
ID:EMP001
名前:山田 太郎
年齢:30
ID:EMP002
名前:佐藤 花子
年齢:27コンソールの表示

この結果が表示されれば、JavaプログラムからH2 Databaseへ接続し、EMPLOYEESテーブルのデータを取得できています。
H2コンソールではなく、Javaプログラムからデータベースの中身を取り出せている点が重要です。
図3:ResultSetから1行ずつ値を取り出す

この図から分かること
ResultSetには、SELECT文で取得した検索結果が格納されています。
rs.nextを実行すると、取り出し対象のレコードが1行進みます。
while文と組み合わせることで、検索結果のレコードを先頭から順番に処理できます。
各行では、rs.getString("ID")、rs.getString("NAME")、rs.getInt("AGE")のように列名を指定して値を取得します。
取得した値は、コンソールに出力したり、JavaBeansに格納したり、JSPへ渡したりできます。
JDBCドライバ読み込み失敗時の対応
SelectEmployees.javaでは、最初にClass.forName("org.h2.Driver")を実行しています。
これは、H2 DatabaseのJDBCドライバを読み込むための処理です。
H2のJDBCドライバが適切に配置されていない場合、ClassNotFoundExceptionが発生します。
このプログラムでは、ClassNotFoundExceptionが発生した場合、IllegalStateExceptionを発生させて処理を終了しています。
try {
Class.forName("org.h2.Driver");
} catch (ClassNotFoundException e) {
throw new IllegalStateException(
"JDBCドライバを読み込めませんでした");
}JDBCドライバを読み込めない状態では、データベース接続もSQL実行もできません。
そのため、プログラムを続けず、設定に問題があることを分かりやすく示しています。
ClassNotFoundExceptionが出たときに確認すること
JDBCドライバの読み込みに失敗した場合は、H2のJDBCドライバが正しく配置されているか確認します。
確認ポイント
| 確認項目 | 内容 |
|---|---|
| JARファイル | h2-x.x.x.jarがあるか |
| 配置場所 | 動的Webプロジェクトならsrc/main/webapp/WEB-INF/libにあるか |
| ファイル名 | ダウンロードしたH2のJARファイルを配置しているか |
| プロジェクト | 実行しているstudyプロジェクトに配置しているか |
| ビルドパス | Javaアプリケーションとして実行する場合に参照できる状態か |
動的WebプロジェクトのWEB-INF/libに配置している場合でも、通常のJavaアプリケーションとして実行するときに参照できない設定になっている場合があります。
Eclipseで実行する場合は、プロジェクトのビルドパスやライブラリの認識状態も確認しましょう。
SQLExceptionが発生したときに確認すること
データベース接続やSQL実行で問題があると、SQLExceptionが発生します。
SelectEmployees.javaでは、SQLExceptionが発生した場合にe.printStackTraceでエラー内容を表示しています。
} catch (SQLException e) {
e.printStackTrace();
}実際の業務システムでは、ログに記録したり、利用者向けのエラー画面を表示したりするなど、より適切な処理を行います。
学習段階では、まずエラー内容をコンソールで確認し、原因を探れるようにしておきます。
SQLExceptionで確認したいこと
| 状況 | 確認すること |
|---|---|
| 接続できない | H2 Databaseが起動しているか |
| 接続先が違う | JDBC URLがjdbc:h2:tcp://localhost/~/studyになっているか |
| テーブルがない | EMPLOYEESテーブルを作成済みか |
| SQLエラー | SELECT文の列名やテーブル名に誤りがないか |
| 認証エラー | ユーザー名sa、パスワード空文字で接続しているか |
| データが表示されない | EMPLOYEESテーブルにレコードが追加されているか |
SQLExceptionは、データベースに関するさまざまな問題を知らせてくれます。
エラーが出た場合は、接続情報、SQL文、テーブルの有無、データの有無を順番に確認しましょう。
JDBCでデータを取得するときに押さえたいこと
JDBCでデータを取得するときは、Javaプログラム、JDBCドライバ、DBMS、データベースの関係を意識することが大切です。
Javaプログラムは、DriverManagerを使ってConnectionを取得します。
ConnectionからPreparedStatementを作成し、SELECT文を実行します。
SELECT文の結果はResultSetとして返ってきます。
ResultSetからrs.nextで1行ずつ進めながら、getStringやgetIntで列の値を取得します。
今回のSelectEmployees.javaでは、EMPLOYEESテーブルから次のデータを取得しました。
取得したデータ
| ID | NAME | AGE |
|---|---|---|
| EMP001 | 山田 太郎 | 30 |
| EMP002 | 佐藤 花子 | 27 |
このように、Javaプログラムからデータベースのレコードを取得できるようになると、ServletやJSPで作るWebアプリケーションでも、データベースの内容を画面に表示できるようになります。
まずはコンソールに表示するJDBCプログラムで流れを理解し、その後、Servlet、DAO、JSPへ役割を分けた構成に発展させていきましょう。
