JDBC の基礎
接続、ステートメント、結果セットです。
「JDBC の基礎」はCoddyKit上の無料Java Academyレッスンです。 これはレッスン1/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはJava Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Java Academyコースには全4レッスンが含まれています。
JDBCとは何ですか?
JDBC(Java Database Connectivity)は、Javaからリレーショナルデータベースにアクセスするための標準APIです。
java.sqlパッケージに含まれています。- 各データベースは、JDBCインターフェースを実装するドライバーを提供します。
Connection、Statement、ResultSetなどのインターフェースに対してコードを記述し、ベンダー固有のクラスを直接使用することはありません。
この抽象化により、同じコードでPostgreSQL、MySQL、H2、Oracleを利用できます。
中核となるインターフェース
主な処理は、次の3つのインターフェースが担います。
Connection— データベースとのオープンなセッションです。Statement/PreparedStatement— SQLを送信します。ResultSet— クエリが返した行をたどるカーソルです。
Connectionは、DriverManagerまたはDataSourceから取得します。
接続を開く
DriverManager.getConnection(url, user, password)は、使用可能なConnectionを返します。
JDBC URLはデータベースを識別します。たとえば、jdbc:postgresql://localhost:5432/shopのように指定します。現在のドライバーは自動的に自身を登録するため、Class.forName(...)を呼び出す必要はありません。
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class Main {
public static void main(String[] args) {
String url = "jdbc:postgresql://localhost:5432/shop";
try (Connection conn = DriverManager.getConnection(url, "app", "secret")) {
System.out.println("Connected: " + !conn.isClosed());
} catch (SQLException e) {
System.out.println("Connection failed: " + e.getMessage());
}
}
}try-with-resources
Connection、Statement、ResultSetはすべてAutoCloseableを実装しています。
必ずtry-with-resourcesブロック内で開き、自動的にクローズされるようにしてください。例外がスローされた場合でもクローズされます。接続を解放しないと、データベースの接続をすぐに使い果たしてしまいます。
- リソースは逆の順序でクローズされます。
finallyブロックは必要ありません。
クエリを実行する
単純なSELECTの場合は、Statementを作成してexecuteQueryを呼び出します。executeQueryはResultSetを返します。
この例では、実際のデータベースがなくても処理の流れを確認できるよう、メモリ内のシミュレーションを使用しています。実際の運用では、SQLは接続先のデータベースに対して実行されます。
import java.util.List;
public class Main {
public static void main(String[] args) {
// Simulated result of: SELECT name FROM users
List<String> names = List.of("Ada", "Linus", "Grace");
System.out.println("Query returned " + names.size() + " rows:");
for (String name : names) {
System.out.println(" - " + name);
}
}
}ResultSetを読み取る
ResultSetは、最初の行の前から始まります。ループ内でrs.next()を呼び出してください。これ以上行がない場合はfalseを返します。
型付きの取得メソッドを使い、列名または1から始まるインデックスで列を読み取ります。
rs.getInt("id")rs.getString("name")rs.getDouble("price")
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class Main {
public static void main(String[] args) {
String url = "jdbc:postgresql://localhost:5432/shop";
try (Connection conn = DriverManager.getConnection(url, "app", "secret");
Statement st = conn.createStatement();
ResultSet rs = st.executeQuery("SELECT id, name FROM users")) {
while (rs.next()) {
System.out.println(rs.getInt("id") + ": " + rs.getString("name"));
}
} catch (SQLException e) {
System.out.println(e.getMessage());
}
}
}書き込みにはexecuteUpdateを使う
INSERT、UPDATE、DELETEにはexecuteUpdateを使用します。executeUpdateはintを返します。これは影響を受けた行数です。
文が結果セットを返すかどうかを事前に判断できない場合に限り、executeを使用してください。
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class Main {
public static void main(String[] args) {
String url = "jdbc:postgresql://localhost:5432/shop";
try (Connection conn = DriverManager.getConnection(url, "app", "secret");
Statement st = conn.createStatement()) {
int rows = st.executeUpdate("DELETE FROM sessions WHERE expired = true");
System.out.println("Deleted " + rows + " rows");
} catch (SQLException e) {
System.out.println(e.getMessage());
}
}
}行をオブジェクトにマッピングする
ほとんどのアプリケーションでは、各行をドメインオブジェクトに変換します。ResultSetをループし、インスタンスを作成します。
これが基本的なパターンです。単独で実行できるようにシミュレーションしています。recordを使うと、マッピングを簡潔に記述できます。
import java.util.ArrayList;
import java.util.List;
public class Main {
record User(int id, String name) {}
public static void main(String[] args) {
// Stand-in for iterating a ResultSet
String[][] rows = {{"1", "Ada"}, {"2", "Linus"}};
List<User> users = new ArrayList<>();
for (String[] row : rows) {
users.add(new User(Integer.parseInt(row[0]), row[1]));
}
users.forEach(System.out::println);
}
}SQLExceptionを処理する
ほぼすべてのJDBCメソッドは、チェック例外であるSQLExceptionをスローします。
この例外には、次のような有用な診断情報が含まれています。
getMessage()— 人間が読めるメッセージです。getSQLState()— 標準の5文字の状態コードです。getErrorCode()— ベンダー固有のエラーコードです。
これらを無視せず、ログに記録してください。
import java.sql.SQLException;
public class Main {
public static void main(String[] args) {
SQLException e = new SQLException("duplicate key", "23505", 7);
System.out.println("Message: " + e.getMessage());
System.out.println("SQLState: " + e.getSQLState());
System.out.println("ErrorCode: " + e.getErrorCode());
}
}DatabaseMetaData
conn.getMetaData()は、データベース自体を説明するDatabaseMetaDataオブジェクトを返します。
このオブジェクトから、製品名やバージョン、サポートされている機能を確認できるほか、テーブルや列の一覧も取得できます。スキーマブラウザーなどのツールは、ベンダー固有の情報をハードコードせずにこの仕組みを利用しています。
一連の処理を組み立てる
一般的な読み取り処理の流れは次のとおりです。
- try-with-resources内で
Connectionを開きます。 Statement(または、より適したPreparedStatement)を作成します。executeQueryを呼び出し、rs.next()でループします。- 列をオブジェクトにマッピングします。
- try-with-resourcesによってすべてをクローズします。
次のレッスンでは、インジェクションからクエリを安全に保護する方法を学びます。
クイックチェック
Statement.executeUpdateは何を返しますか?
まとめ
JDBCの基本的な処理の流れを理解しました。
DriverManager.getConnectionによってConnectionを開きます。StatementでSQLを送信します。executeQueryはResultSetを返し、executeUpdateは影響を受けた行数を返します。rs.next()と型付きの取得メソッドを使って反復処理します。- 必ずtry-with-resourcesを使用し、状態コードとエラーコードを使って
SQLExceptionを処理します。
よくある質問
「JDBC の基礎」レッスンは無料ですか?
はい。「JDBC の基礎」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Java Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Java Academyコースには全4レッスンが含まれています。
「JDBC の基礎」で何を学びますか?
接続、ステートメント、結果セットです。 ブラウザで直接実行するハンズオンコードでJava Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
Java Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのJava Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン1/4です。
「JDBC の基礎」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このJava Academyレッスンでコードを書いて実行できますか?
はい。すべてのJava Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。