解説 · セクション 1

interface を使いこなす

JDBC で「いきなり要求される」interface 変数の感覚を、身近な例えと図で押さえます。読み終わったら問題に挑戦してください。

読み終わったら問題に挑戦できます → 演習に進む

身近に置き換えると

データベース操作を「銀行の窓口」でのやり取りに置き換えてみましょう。あなたが銀行で振り込みをしたいとき、まずは「総合案内」に行き、要件を伝えて「担当窓口」に案内してもらいます。次に、担当窓口で「振込用紙」をもらい、そこに記入して提出すると、最後に「明細書」を受け取ります。

A銀行に行っても、B銀行に行っても、この「案内→窓口→用紙→明細」という手順(ルール)は同じです。Javaのデータベース接続(JDBC)もこれと全く同じで、データベースの種類が変わっても、共通のルール(interface)に沿って操作を進めていきます。

3 行でまとめると

  • interface は new できないため、専用の案内係(DriverManager)から実体を受け取る。
  • 戻り値はすべて interface 型(Connection, PreparedStatement, ResultSet)の変数で順番に受け取っていく。
  • interface 越しに操作するため、裏のデータベース(実装)が変わっても Java の呼び出しコードは変わらない。

図で見ると

classDiagram
    class DriverManager {
        +getConnection() Connection
    }
    class Connection {
        <>
        +prepareStatement() PreparedStatement
    }
    class PreparedStatement {
        <>
        +executeQuery() ResultSet
    }
    class ResultSet {
        <>
    }
    
    DriverManager ..> Connection : 戻り値として渡す
    Connection ..> PreparedStatement : 戻り値として渡す
    PreparedStatement ..> ResultSet : 戻り値として渡す

案内係(DriverManager)から始まり、次々と interface の戻り値を受け取ってバトンリレーのように処理を進めていくのが JDBC の基本構造です。

順を追って理解する

1. interface は new できない

Javaのルールとして、interface はあくまで「操作の約束事」であり、実体がないため new Connection() のように直接生み出すことはできません。実体を作るには、代わりに作ってくれる別の仕組みが必要です。

2. 案内係(ファクトリ)から実体をもらう

そこで登場するのが DriverManager クラスです。このクラスの getConnection()static メソッド(クラスに直接お願いできる案内係)になっており、これを呼び出すことで Connection(担当窓口)の実体をもらいます。受け取る左辺の変数は、interface 型である Connection 型で宣言します。

3. 窓口から用紙をもらう(prepareStatement の位置づけ)

担当窓口(Connection)につながったら、次は「こんなSQLを実行したい」と伝えて準備をします。ConnectionprepareStatement() メソッドを呼び出すと、SQLの準備用紙である PreparedStatement 型の戻り値がもらえます。これも interface 型の変数で受け取ります。

4. 実行して結果をもらう

準備用紙(PreparedStatement)に条件などを書き込んだら、executeQuery() メソッドで実行します。すると、データベースから検索結果が ResultSet 型(明細書)として返ってきます。これもやはり interface です。

5. なぜすべて interface なのか?(実装の差し替え)

MySQL、PostgreSQL、Oracleなど、データベースによって裏側の通信の仕組み(実装)はバラバラです。しかし、Java側がすべて ConnectionPreparedStatement といった共通の interface 越しに操作するようにしておけば、接続先のデータベースを変えても、Javaのコードを一切書き換える必要がなくなります。これを「実装の差し替え」と呼びます。

応用ではこう書く

// 1. 案内係 (DriverManager) から 担当窓口 (Connection) をもらう
// ※ getConnection は static メソッドなので、クラス名から直接呼び出します
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost/mydb", "user", "pass");

// 2. 窓口 (Connection) から 準備用紙 (PreparedStatement) をもらう
// ※ ここで実行したいSQLの骨組みを渡します
PreparedStatement pstmt = conn.prepareStatement("SELECT name FROM users WHERE id = ?");

// 3. 準備用紙に具体的な値を書き込む
pstmt.setInt(1, 100);

// 4. 実行して、結果の明細 (ResultSet) をもらう
ResultSet rs = pstmt.executeQuery();

// 5. 明細 (ResultSet) からデータを読み取る
while (rs.next()) {
    System.out.println(rs.getString("name"));
}

// ※ 左辺の型 (Connection, PreparedStatement, ResultSet) はすべて interface です。

このように、自分で new をするのではなく、メソッドの戻り値として interface を受け取り、その interface のメソッドを呼んでさらに次の interface を受け取る、という流れでコードを書きます。

よくある誤解

誤解: Connection conn = new Connection(); と書いてしまう

正しくは: Connection は interface なので new できません。必ず DriverManager.getConnection(...) のように、実体を作って返してくれるメソッド(ファクトリ)の戻り値として受け取ります。

誤解: データベースの種類(MySQLやOracleなど)ごとに、Javaのメソッドの呼び方を変えなければならない

正しくは: 変えなくて大丈夫です。左辺の変数をすべて共通の interface(Connection など)で宣言しているため、最初の getConnection() で渡す接続先URLを変えるだけで、その後の prepareStatementexecuteQuery といった呼び出しコードは全く同じまま動きます。

つまずいたら

このトピックで詰まったら基礎復習へ: 章 4 インターフェース

準備できたら問題に挑戦 → 演習に進む (7 問)