第05章 データベース

05_database

第05章 データベース・SQL・MySQL・JDBC

この章の読み方: 本文の基本説明、直後の発展解説、例題、演習の順に読んでください。専門用語は初めて出てきた箇所で意味を確認し、コードの予想結果を考えてから実行します。

章末の演習は、それまでの本文の内容を使って解けるように設計しています。

用語の表記: 全10章共通の用語集 と表記を揃えています。

対象:プログラミング未経験者/Java初学者
推奨環境:Windows 11、JDK 21、Eclipse、Maven、MySQL Community Server 8.4 LTS
方針:無料ツールを使用し、DBとプログラムの実行はローカルPCで完結

この章では、これまで扱ってきた商品データをデータベースに保存し、SQLで検索・変更し、Javaから取り扱う方法を学びます。新しい用語を最初に説明し、操作の理由と確認方法を省略しないようにしています。例を読むだけでは身につきません。

毎節でSQLを実行し、変更前後のデータを必ず確かめてください。

教材ファイル:examples/05_database/sql/ に初期化用SQL、examples/05_database/src/main/java/ にJavaサンプル、exercises/05_database/ に演習と指導者用解答があります。

安全上の注意:教材のDROPやDELETEは学習専用DBだけで実行してください。業務DB、共有DBでは決してそのまま実行しないでください。パスワードは教材・Git・スクリーンショットに含めないでください。


独学演習: 学んだ内容の確認には、第05章の実行予想・段階別ヒント・自己チェックを使ってください。本文の説明を読んだあと、自分で出力を予想してから試します。

00. 学習前の準備と到達目標

第04章では商品をCSVファイルから読み込みました。ファイルは学習に適していますが、複数の利用者がデータを更新したり、商品と注文の関係を安全に管理したりする場面では、データベースが適しています。

この章では「データがどう保存されるのか」から学習し、最後にJavaから検索・登録・更新・削除を行います。

目標は、テーブル構造と主キー・外部キーを説明でき、SELECT/INSERT/UPDATE/DELETEを書き、PreparedStatementを安全に利用し、トランザクションの意味を理解することです。

前提は第01〜04章、Windows 11、JDK 21、Eclipse、Mavenです。所要時間の目安は12〜18時間です。最初から暗記せず、SQLを1行ずつ実行して結果を確認してください。

この節の独学チェック:00. 学習前の準備と到達目標

確認問題: SQL学習前に確認すべきJavaの知識と準備は何ですか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

前章のコードで使った文字列・例外・クラスを思い出しましょう。

ヒント2

SQLクライアントとJavaプログラムの両方が動くには、DB側で何が必要でしょうか。

ヒント3

Java側の前提知識とMySQLの接続準備を、別々にチェックしてください。

模範解答と理由

Javaの基本的な文字列・例外・クラスを理解し、MySQLの接続先と管理者情報を準備します。

この節の自己採点基準(2点満点)

独立して判定する正答要素

  1. 1点: Javaの文字列・例外・クラスの基礎を確認する。
  2. 1点: ローカルMySQLの接続先・ログイン情報を準備する。

満点の正答例: Javaの基本的な文字列・例外・クラスを理解し、MySQLの接続先と管理者情報を準備します。

部分点の判定: 部分正答例:「Javaの文字列・例外・クラスの基礎を確認する」。この記述だけなら1点で、残る正答要素は未達です。

誤答・採点ミスの例: 不十分な解答例:「Javaの文字列・例外・クラスの基礎を確認する」。他の必須要素を欠いたまま満点と判定するのは誤りです。

合格条件:2/2点。 正答の言い換えは認めます。

復習先: この節「00. 学習前の準備と到達目標」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

01. データベースとRDBMSとは

データベースは、情報を整理して保存し、必要な情報を検索したり変更したりする仕組みです。MySQLは、表の形で情報を管理する「リレーショナルデータベース管理システム(RDBMS)」です。

表はテーブル、横一行は行(レコード)、縦の項目は**列(カラム)**と呼びます。例えば products テーブルは商品番号・商品名・価格・在庫数を持ちます。

ファイルと異なり、データベースは検索条件や更新をSQLという共通の言語で指示できます。データベースサーバーはデータを保存・管理する側、クライアントは指示を送る側です。今回は同じPCに両方を置き、インターネット上のDBは使いません。

この節の独学チェック:01. データベースとRDBMSとは

確認問題: productsの1行とproductsテーブル全体の違いは何ですか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

商品番号A01の行を例にして、横方向と縦方向を考えます。

ヒント2

1商品を示す単位と複数商品を入れる器を分けてください。

ヒント3

同じ列名を持つ行が複数並んでいる状態を想像してください。

模範解答と理由

1行は1件の商品のレコード、テーブルは同じ列構造を持つレコードの集合です。

この節の自己採点基準(2点満点)

独立して判定する正答要素

  1. 1点: productsの1行は1件の商品レコードである。
  2. 1点: productsテーブルは共通の列構造を持つレコードの集合である。

満点の正答例: 1行は1件の商品のレコード、テーブルは同じ列構造を持つレコードの集合です。

部分点の判定: 部分正答例:「productsの1行は1件の商品レコードである」。この記述だけなら1点で、残る正答要素は未達です。

誤答・採点ミスの例: 不十分な解答例:「productsの1行は1件の商品レコードである」。他の必須要素を欠いたまま満点と判定するのは誤りです。

合格条件:2/2点。 正答の言い換えは認めます。

復習先: この節「01. データベースとRDBMSとは」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

02. WindowsにMySQL Community Serverを導入

MySQL 8.4 LTSのCommunity Serverを使用します。

公式のダウンロードページ https://dev.mysql.com/downloads/mysql/8.4.html を開き、Windows向けMSIを選びます。商用サポート付き製品を購入する必要はありません。

MSIを起動し、MySQL ServerとMySQL Configuratorを導入します。画面名称は配布時期で異なる場合がありますが、設定の意味を確認してから進んでください。

ConfiguratorでローカルのTCP/IP接続ポートを 3306 に設定します。3306はMySQLの標準的なポート番号です。

他サービスが使用している場合は競合するため、空いている別の番号に変更し、以降の接続URLも合わせます。rootは管理者アカウントです。推測されにくいパスワードを設定し、教材やGitに記載しないでください。

Windowsサービスの設定を終え、MySQL Serverが起動していることを確認します。ネットワークに公開する必要はありません。ファイアウォールを外部向けに開放せず、ローカル接続で学習してください。

インストールが失敗した場合はWindowsの「サービス」でMySQLサービスの状態、ポート競合、必要なVisual C++ランタイムを確認してください。

この節の独学チェック:02. WindowsにMySQL Community Serverを導入

確認問題: WindowsにMySQLを入れた後、サービスが開始しているか確認する理由は何ですか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

インストールしただけで通信先のプログラムは動くでしょうか。

ヒント2

SQLを受け付けるのはクライアントとサーバーのどちらでしょうか。

ヒント3

Windowsサービスの状態と接続できる条件を結び付けてください。

模範解答と理由

MySQLサーバーが停止していると、SQLクライアントから接続できないためです。

この節の自己採点基準(1点満点)

独立して判定する正答要素

  1. 1点: MySQLサーバーが停止していると、SQLクライアントから接続できないためです。

満点の正答例: MySQLサーバーが停止していると、SQLクライアントから接続できないためです。

部分点の判定: 正答要素は1つなので部分点はありません。意味が一致すれば1点、異なれば0点です。

誤答・採点ミスの例: 不十分な解答例:「よく分からないが、そのまま進めればよい」。正答条件「MySQLサーバーが停止していると、SQLクライアントから接続できないためです」を示していないので0点です。

合格条件:1/1点。 正答の言い換えは認めます。

復習先: この節「02. WindowsにMySQL Community Serverを導入」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

03. MySQLコマンドラインで接続

スタートメニューからMySQL Command Line Clientを使うか、コマンドプロンプトからMySQLの bin フォルダーに移動して次を実行します。

mysql コマンドが見つからない場合は、まだPATHに登録されていない可能性があります。実行ファイルの絶対パスを指定しても構いません。-u は利用者名、-p はパスワードを対話入力する指定です。

コマンドにパスワードを直接記載すると履歴に残る危険があるため避けます。入力時に文字が表示されなくても異常ではありません。接続できたら SELECT VERSION(); でサーバーのバージョンを確認します。

セミコロンでSQL文が終わることも確認してください。終了するときは exit; です。

mysql -u root -p
SELECT VERSION();

この節の独学チェック:03. MySQLコマンドラインで接続

確認問題: mysql> が表示されている場所とPowerShellで入力できるコマンドは同じですか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

コマンド入力前に表示されているプロンプトを見ましょう。

ヒント2

mysql> と PS> のどちらがSQL文を解釈するのでしょうか。

ヒント3

SELECTとdirをそれぞれどこで入力するか考えてください。

模範解答と理由

違います。mysql>ではSQLやMySQLクライアントのコマンド、PowerShellではOSのコマンドを実行します。

この節の自己採点基準(2点満点)

独立して判定する正答要素

  1. 1点: mysql>ではSQLとMySQLクライアント用の命令を入力する。
  2. 1点: PowerShellではOS用のコマンドを入力する。

満点の正答例: 違います。mysql>ではSQLやMySQLクライアントのコマンド、PowerShellではOSのコマンドを実行します。

部分点の判定: 部分正答例:「mysql>ではSQLとMySQLクライアント用の命令を入力する」。この記述だけなら1点で、残る正答要素は未達です。

誤答・採点ミスの例: 不十分な解答例:「mysql>ではSQLとMySQLクライアント用の命令を入力する」。他の必須要素を欠いたまま満点と判定するのは誤りです。

合格条件:2/2点。 正答の言い換えは認めます。

復習先: この節「03. MySQLコマンドラインで接続」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

04. 学習用DBと専用ユーザーを作る

管理者アカウントで学習用DBと専用ユーザーを作成します。CREATE DATABASE はデータベースの作成、CREATE USER はログイン可能な利用者の追加です。

'training_user'@'localhost' の後半は、接続元をローカルPCに限定する指定です。GRANT は対象DBに対して許可する操作を設定します。

実務では必要最小限の権限が基本ですが、ここではDB内のテーブル作成を行うため SELECT, INSERT, UPDATE, DELETE, CREATE, ALTER, DROP, REFERENCES を与えます。

パスワード文字列 CHANGE_ME は例示にすぎません。必ず独自のパスワードに置き換え、Gitへ登録しないこと。

なお、CREATE USER IF NOT EXISTS は同じ名前のユーザーがすでに存在する場合、そのユーザーのパスワードを変更しません。

再実習でログインできないときは、まず既存ユーザーと設定済みパスワードを確認し、パスワード変更が必要なら管理者として ALTER USER を適切に実行します。

入力内容は付属の sql/00_setup_admin.sql にも掲載しましたが、配布ファイルに実パスワードを記入して保存しないでください。以降は原則 training_user で接続します。

CREATE DATABASE IF NOT EXISTS training_db CHARACTER SET utf8mb4;
CREATE USER IF NOT EXISTS 'training_user'@'localhost' IDENTIFIED BY 'CHANGE_ME';
GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, ALTER, DROP, REFERENCES
  ON training_db.* TO 'training_user'@'localhost';
mysql -u training_user -p training_db

理解を深める:安全な練習DBを作る

この練習では第05章専用の training_db 内で作業します。先行する章のDB定義と混ざらないようにします。授業用PC以外の本番DBには実行しないでください。

CREATE DATABASE IF NOT EXISTS training_db CHARACTER SET utf8mb4;
USE training_db;
CREATE TABLE IF NOT EXISTS sql_practice_products (
  id INT PRIMARY KEY,
  name VARCHAR(100) NOT NULL,
  price INT NOT NULL
);
CREATE TABLE IF NOT EXISTS sql_practice_order_items (
  id INT PRIMARY KEY,
  product_id INT NOT NULL,
  quantity INT NOT NULL,
  FOREIGN KEY (product_id) REFERENCES sql_practice_products(id)
);
DELETE FROM sql_practice_order_items;
DELETE FROM sql_practice_products;
INSERT INTO sql_practice_products VALUES
 (1, 'ノート', 100), (2, 'ペン', 150), (3, '消しゴム', 80);
INSERT INTO sql_practice_order_items VALUES
 (1, 1, 2), (2, 2, 1), (3, 1, 1);

CREATE TABLE は表を作成します。PRIMARY KEY は重複しない識別子です。NOT NULL はNULLを禁止します。FOREIGN KEY は別表との関係を制限します。

初期化時は先に子表の明細を削除してから親表の商品を削除します。

この節の独学チェック:04. 学習用DBと専用ユーザーを作る

確認問題: training_userをrootではなく別に作る理由は何ですか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

rootアカウントに許されている操作を考えましょう。

ヒント2

学習アプリが他のDBの管理までできる必要があるでしょうか。

ヒント3

権限を利用目的に限定する原則を使って答えてください。

模範解答と理由

学習用アプリに必要なDB権限だけを与え、管理者の広すぎる権限を使わないためです。

この節の自己採点基準(1点満点)

独立して判定する正答要素

  1. 1点: 学習用アプリに必要なDB権限だけを与え、管理者の広すぎる権限を使わないためです。

満点の正答例: 学習用アプリに必要なDB権限だけを与え、管理者の広すぎる権限を使わないためです。

部分点の判定: 正答要素は1つなので部分点はありません。意味が一致すれば1点、異なれば0点です。

誤答・採点ミスの例: 不十分な解答例:「よく分からないが、そのまま進めればよい」。正答条件「学習用アプリに必要なDB権限だけを与え、管理者の広すぎる権限を使わないためです」を示していないので0点です。

合格条件:1/1点。 正答の言い換えは認めます。

復習先: この節「04. 学習用DBと専用ユーザーを作る」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

05. テーブル・データ型・主キー

商品のデータを入れるテーブルを設計します。INT は整数、VARCHAR(100) は最大100文字の可変長文字列、DECIMAL(10,2) は小数を扱う型です。

金額については丸め誤差が問題になる場合があるため、ここでは DECIMAL を選びます。NOT NULL は値がない状態を禁止します。

PRIMARY KEY は行を一意に識別する主キーで、同じ値を二つの行に割り当てることはできません。AUTO_INCREMENT は新しい行を登録したときに番号を自動採番する機能です。

CHECK は価格や在庫数がマイナスにならないよう制約を設けています。

CREATE TABLE products (
  id INT PRIMARY KEY AUTO_INCREMENT,
  name VARCHAR(100) NOT NULL,
  price DECIMAL(10,2) NOT NULL,
  stock INT NOT NULL DEFAULT 0,
  CONSTRAINT chk_price CHECK (price >= 0),
  CONSTRAINT chk_stock CHECK (stock >= 0)
);

SQLの実行後 SHOW TABLES; と DESCRIBE products; を使うと、作成結果を確認できます。

理解を深める:なぜデータを表に分けるのか

注文のたびに商品の名前と値段をすべて注文レコードへ重複して保存すると、商品名変更の際に多数の場所を直す必要が生じます。一方、商品テーブルと注文明細テーブルを分け、商品IDで関連付ければ、どの商品が注文されたかを特定できます。

ただし、注文当時の価格を残すには、注文明細に購入時単価を保持するなど業務上の要件に応じた設計が必要です。単に重複を減らせばよいわけではありません。

products                               order_items
+----+-----------+-------+              +----------+------------+----------+
| id | name      | price |              | order_id | product_id | quantity |
+----+-----------+-------+              +----------+------------+----------+
|  1 | ペン      |   120 | ← product_id |       10 |          1 |        2 |
|  2 | ノート    |   250 | ← product_id |       10 |          2 |        1 |
+----+-----------+-------+              +----------+------------+----------+

products.id は各商品を一意に特定する主キーです。order_items.product_id は他の表の商品を指す外部キーとして設定できます。

理解を深める:テーブルを図で理解する

products(商品)                         order_items(注文明細)
+----+----------+-------+               +----+------------+----------+
| id | name     | price |               | id | product_id | quantity |
+----+----------+-------+               +----+------------+----------+
|  1 | ノート   |   100 |<──外部キー─────|  1 |     1      |     2    |
|  2 | ペン     |   150 |<──外部キー─────|  2 |     2      |     1    |
+----+----------+-------+               +----+------------+----------+

products.id は商品を一意に識別する主キーです。order_items.product_id は同じ商品IDを指す外部キーです。JOINは、関連する列同士の値を使って複数の表を関連付け、結果を取得するSQLです。

外部キー制約がある場合、存在しない商品IDを明細へ登録しないように制限できます。

この節の独学チェック:05. テーブル・データ型・主キー

確認問題: product_idにPRIMARY KEYを設定すると、どんな値が禁止されますか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

同じIDを2商品へ割り当てた状態を想像します。

ヒント2

IDが未設定なら、行を一意に選べるでしょうか。

ヒント3

主キーの「一意性」と「値の必須性」を区別してください。

模範解答と理由

同じIDの重複とNULLが禁止されます。主キーは各行を一意に特定します。

この節の自己採点基準(2点満点)

独立して判定する正答要素

  1. 1点: 同じIDの重複とNULLが禁止されます。
  2. 1点: 主キーは各行を一意に特定します。

満点の正答例: 同じIDの重複とNULLが禁止されます。主キーは各行を一意に特定します。

部分点の判定: 部分正答例:「同じIDの重複とNULLが禁止されます」。この記述だけなら1点で、残る正答要素は未達です。

誤答・採点ミスの例: 不十分な解答例:「同じIDの重複とNULLが禁止されます」。他の必須要素を欠いたまま満点と判定するのは誤りです。

合格条件:2/2点。 正答の言い換えは認めます。

復習先: この節「05. テーブル・データ型・主キー」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

図解:テーブルと主キー

テーブルと主キー

図の読み方:1行が1レコード、列が項目、主キーは行を一意に識別します。

06. INSERT:データの登録

INSERT INTO はテーブルに新しい行を追加するSQLです。丸括弧の中の列名と VALUES の値は順番が対応します。主キー id は自動採番されるので指定しません。

文字列はシングルクォートで囲み、数値はそのまま記載します。まずSQLを実行し、続いて SELECT * FROM products; で追加されたことを確認してください。

INSERT INTO products (name, price, stock)
VALUES ('ノート', 180.00, 20), ('ペン', 120.00, 35), ('消しゴム', 90.00, 15);
SELECT * FROM products;

同じINSERTを再実行すると別の行が追加される点にも注意します。データを初期状態に戻したいときは付属のセットアップSQLを使い、実務の共有DBでは初期化SQLを不用意に実行しないでください。

この節の独学チェック:06. INSERT:データの登録

確認問題: INSERT INTO products(name,price) VALUES ('鉛筆',100) はどの操作ですか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

SQLの冒頭にある動詞を確認してください。

ヒント2

列名とVALUESの値を1対1で対応させてみましょう。

ヒント3

既存行への変更なのか、新規行の追加なのか判定してください。

模範解答と理由

productsに商品名「鉛筆」、価格100の新しい行を登録します。実際の列構成との一致が必要です。

この節の自己採点基準(2点満点)

独立して判定する正答要素

  1. 1点: 新しい行を登録するINSERTであると説明する。
  2. 1点: 商品名が鉛筆、価格が100になると答える。

満点の正答例: productsに商品名「鉛筆」、価格100の新しい行を登録します。実際の列構成との一致が必要です。

部分点の判定: 部分正答例:「新しい行を登録するINSERTであると説明する」。この記述だけなら1点で、残る正答要素は未達です。

誤答・採点ミスの例: 不十分な解答例:「新しい行を登録するINSERTであると説明する」。他の必須要素を欠いたまま満点と判定するのは誤りです。

合格条件:2/2点。 正答の言い換えは認めます。

復習先: この節「06. INSERT:データの登録」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

07. SELECT:検索の基本

SQLで行を取得するには SELECT を使います。SELECT name, price FROM products; は必要な列だけを取得します。

* は全列を意味しますが、業務プログラムでは用途が明確な列名を指定するほうが変更の影響を把握しやすくなります。WHERE は条件です。

ORDER BY price DESC は価格が高い順、ASC は低い順に並べます。LIMIT 2 は最大2件に絞ります。

SELECT id, name, price FROM products WHERE price >= 100 ORDER BY price DESC LIMIT 2;

実行前にどの商品が表示されるか予想してください。表示結果と予想が違う場合は条件式、価格の型、並び順を順に見直します。

この節の独学チェック:07. SELECT:検索の基本

確認問題: SELECT * FROM products WHERE price >= 200 は何を返しますか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

WHEREの比較演算子に注目してください。

ヒント2

価格199・200・201の商品があると仮定します。

ヒント3

どの行が残り、SELECTの*がどの列を返すか考えます。

模範解答と理由

productsのうち価格が200以上の行だけを返します。*は全列を示します。

この節の自己採点基準(2点満点)

独立して判定する正答要素

  1. 1点: productsのうち価格が200以上の行だけを返します。
  2. 1点: *は全列を示します。

満点の正答例: productsのうち価格が200以上の行だけを返します。*は全列を示します。

部分点の判定: 部分正答例:「productsのうち価格が200以上の行だけを返します」。この記述だけなら1点で、残る正答要素は未達です。

誤答・採点ミスの例: 不十分な解答例:「productsのうち価格が200以上の行だけを返します」。他の必須要素を欠いたまま満点と判定するのは誤りです。

合格条件:2/2点。 正答の言い換えは認めます。

復習先: この節「07. SELECT:検索の基本」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

08. 条件式・LIKE・NULL

条件は AND と OR で組み合わせられます。LIKE '%ノート%' は名前に「ノート」を含む行を検索します。% は任意の文字列を表すワイルドカードです。

NULL は0でも空文字列でもなく、値が存在しないことを示します。NULL を判定するときは = NULL ではなく IS NULL を使います。

今回の products.name はNOT NULLなのでNULLになりませんが、注文の備考などでは必要になる考え方です。

SELECT name, stock FROM products WHERE price >= 100 AND stock > 0;
SELECT name FROM products WHERE name LIKE '%ノート%';

この節の独学チェック:08. 条件式・LIKE・NULL

確認問題: price IS NULL と price = NULL は同じ意味ですか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

NULLを数値0や空文字と同一視しないでください。

ヒント2

SQLで未知の値との比較の結果を思い出しましょう。

ヒント3

NULL専用の述語と通常の等値比較を見比べてください。

模範解答と理由

同じではありません。NULL判定にはIS NULLを使います。= NULLは真になりません。

この節の自己採点基準(3点満点)

独立して判定する正答要素

  1. 1点: 同じではありません。
  2. 1点: NULL判定にはIS NULLを使います。
  3. 1点: = NULLは真になりません。

満点の正答例: 同じではありません。NULL判定にはIS NULLを使います。= NULLは真になりません。

部分点の判定: 部分正答例:「同じではありません」。この記述だけなら1点で、残る正答要素は未達です。

誤答・採点ミスの例: 不十分な解答例:「同じではありません」。他の必須要素を欠いたまま満点と判定するのは誤りです。

合格条件:3/3点。 正答の言い換えは認めます。

復習先: この節「08. 条件式・LIKE・NULL」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

09. UPDATEとDELETE:安全な変更

UPDATE は既存の行を変更し、DELETE は行を削除します。どちらも WHERE を省くと対象テーブルの全行に影響する可能性があります。そこで変更前に同じ条件のSELECTを実行し、件数やIDを確かめます。

UPDATE products SET stock = 18 WHERE id = 1; の実行後は再検索して値を確認します。

練習では DELETE FROM products WHERE id = 3; を使いますが、実務では削除してよいデータか、関連する他テーブルの行がないかも確認が必要です。

SELECT * FROM products WHERE id = 1;
UPDATE products SET stock = 18 WHERE id = 1;
SELECT * FROM products WHERE id = 1;

変更SQLを安易に繰り返し実行すると期待しない状態になる場合があります。

理解を深める:UPDATEとDELETEを安全に実行する理由

SELECT * FROM products WHERE id = 1;
UPDATE products SET price = 130 WHERE id = 1;
SELECT * FROM products WHERE id = 1;

更新する前にSELECTで対象を確認します。WHERE を省略すると複数行すべてを変更するおそれがあるからです。DELETEも同様です。最初は使い捨ての学習用データで実行し、件数を確認する習慣を付けてください。

この節の独学チェック:09. UPDATEとDELETE:安全な変更

確認問題: UPDATE products SET price=0 をWHEREなしで実行する危険は何ですか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

WHEREが省略されたUPDATEの対象を考えましょう。

ヒント2

productsに10行あると仮定して変更件数を予想します。

ヒント3

事前に同じWHEREでSELECTする手順を考えてください。

模範解答と理由

全行の商品価格を0に変更してしまいます。変更対象の条件を先にSELECTで確認します。

この節の自己採点基準(2点満点)

独立して判定する正答要素

  1. 1点: 全行の商品価格を0に変更してしまいます。
  2. 1点: 変更対象の条件を先にSELECTで確認します。

満点の正答例: 全行の商品価格を0に変更してしまいます。変更対象の条件を先にSELECTで確認します。

部分点の判定: 部分正答例:「全行の商品価格を0に変更してしまいます」。この記述だけなら1点で、残る正答要素は未達です。

誤答・採点ミスの例: 不十分な解答例:「全行の商品価格を0に変更してしまいます」。他の必須要素を欠いたまま満点と判定するのは誤りです。

合格条件:2/2点。 正答の言い換えは認めます。

復習先: この節「09. UPDATEとDELETE:安全な変更」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

10. 集計:COUNT・SUM・GROUP BY

商品の件数を数えるには COUNT(*)、在庫数の合計には SUM(stock) を使用します。集計結果は通常1行になります。GROUP BY は同じ値の行をまとめて集計する構文です。

ここでは理解しやすいように、価格帯を条件式で分けます。HAVING はグループ化した後の集計結果に条件を指定するときに利用します。

SELECT COUNT(*) AS product_count, SUM(stock) AS total_stock FROM products;
SELECT CASE WHEN price >= 100 THEN '100以上' ELSE '100未満' END AS price_group,
       COUNT(*) AS count_products
FROM products GROUP BY CASE WHEN price >= 100 THEN '100以上' ELSE '100未満' END;

AS は結果の列に読みやすい名前を付けるための別名です。

この節の独学チェック:10. 集計:COUNT・SUM・GROUP BY

確認問題: 100,200,200の3商品のCOUNT(*)とSUM(price)はどうなりますか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

COUNTは件数、SUMは数値の合計を求めます。

ヒント2

価格100・200・200を紙に書き、件数と総和を別に計算します。

ヒント3

問われていないGROUP BYの話と、求める2値を区別しましょう。

模範解答と理由

COUNT(*)は3、SUM(price)は500です。GROUP BYを使うとグループ単位に集計できます。

この節の自己採点基準(2点満点)

独立して判定する正答要素

  1. 1点: COUNT(*)が3と答える。
  2. 1点: SUM(price)が500と答える。

満点の正答例: COUNT(*)は3、SUM(price)は500です。GROUP BYを使うとグループ単位に集計できます。

部分点の判定: 部分正答例:「COUNT(*)が3と答える」。この記述だけなら1点で、残る正答要素は未達です。

誤答・採点ミスの例: 不十分な解答例:「COUNT(*)が3と答える」。他の必須要素を欠いたまま満点と判定するのは誤りです。

合格条件:2/2点。 正答の言い換えは認めます。

復習先: この節「10. 集計:COUNT・SUM・GROUP BY」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

図解:GROUP BYと集計

GROUP BYと集計

図の読み方:GROUP BYは指定列の値が同じ行をまとめ、SUMなどで集計します。

11. 複数テーブルと外部キー

実務では商品と注文を一つのテーブルに混ぜず、役割に応じて分けます。orders は注文そのもの、order_items は注文に含まれる商品と数量を保持します。

order_items.product_id は products.id を参照し、外部キー(FOREIGN KEY)で存在しない商品を参照しないよう制限します。

INNER JOIN は複数テーブルの関係を辿って列をまとめて取得します。JOINの接続条件を間違えると件数が不自然に増えるため、ON の左右の列が何を示すのか確認します。

SELECT o.id AS order_id, p.name, oi.quantity
FROM orders o
INNER JOIN order_items oi ON oi.order_id = o.id
INNER JOIN products p ON p.id = oi.product_id
ORDER BY o.id, p.id;

同梱の 01_schema.sql と 02_seed.sql にテーブル作成と初期データを掲載しています。

理解を深める:JOINでは結合条件と結び付く行を確認する

SELECT p.name, oi.quantity
FROM order_items AS oi
INNER JOIN products AS p ON p.id = oi.product_id
WHERE oi.order_id = 10;

FROM で注文明細を読み、INNER JOIN で商品表を結び、ON に結合条件を書きます。WHERE は注文ID10に絞る条件です。上記のデータなら「ペン 2」「ノート 1」が結果です。

ON を間違えて条件を外すと、意図しない組み合わせの行が増えます。LEFT JOIN は左側に対応先がない場合でも左側の行を残します。実データで差を確認してください。

理解を深める:SELECT → JOIN → GROUP BY

SELECT id, name, price FROM sql_practice_products ORDER BY id;

期待値は3件です。次のSQLでは明細と商品を結合し、各明細の金額を求めます。

SELECT i.id, p.name, i.quantity, p.price * i.quantity AS subtotal
FROM sql_practice_order_items AS i
JOIN sql_practice_products AS p ON p.id = i.product_id
ORDER BY i.id;

期待値は ノート 200、ペン 150、ノート 100 の順です。次は商品別に集計します。

SELECT p.name, SUM(i.quantity) AS total_quantity,
       SUM(p.price * i.quantity) AS total_amount
FROM sql_practice_order_items AS i
JOIN sql_practice_products AS p ON p.id = i.product_id
GROUP BY p.id, p.name
ORDER BY p.id;

期待値はノートが数量3・金額300、ペンが数量1・金額150です。明細がない消しゴムはINNER JOINでは結果に現れません。すべての商品を表示したいときはLEFT JOINが候補です。

この節の独学チェック:11. 複数テーブルと外部キー

確認問題: orders.product_idをproducts.product_idへの外部キーにする目的は何ですか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

注文側のIDが商品側にない場合を考えてください。

ヒント2

参照先が削除・未登録の場合の整合性を想像します。

ヒント3

外部キーが何の関係をDBに検査させるのか説明してください。

模範解答と理由

存在しない商品IDを注文が参照しないように、参照整合性をDBで守るためです。

この節の自己採点基準(1点満点)

独立して判定する正答要素

  1. 1点: 存在しない商品IDを注文が参照しないように、参照整合性をDBで守るためです。

満点の正答例: 存在しない商品IDを注文が参照しないように、参照整合性をDBで守るためです。

部分点の判定: 正答要素は1つなので部分点はありません。意味が一致すれば1点、異なれば0点です。

誤答・採点ミスの例: 不十分な解答例:「よく分からないが、そのまま進めればよい」。正答条件「存在しない商品IDを注文が参照しないように、参照整合性をDBで守るためです」を示していないので0点です。

合格条件:1/1点。 正答の言い換えは認めます。

復習先: この節「11. 複数テーブルと外部キー」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

図解:外部キーとJOIN

外部キーとJOIN

図の読み方:外部キーは別テーブルの行を参照し、JOINで関連するデータを結び付けます。

12. インデックスとEXPLAINの入門

データ件数が増えると、検索のたびにテーブルの行を順番に調べる処理が遅くなる場合があります。インデックスは特定の列を検索しやすくする仕組みです。

ただし追加するほど更新コストや保存領域が増えるため、何にでも付ければよいわけではありません。EXPLAIN SELECT ... はMySQLがどのようにSQLを実行する予定かを表示します。

まず機能を知ることを目標とし、速度の優劣を決めつけないでください。

CREATE INDEX idx_products_name ON products(name);
EXPLAIN SELECT id, name FROM products WHERE name = 'ノート';

少量の学習データではインデックスが使われない場合があります。それ自体が故障ではありません。

この節の独学チェック:12. インデックスとEXPLAINの入門

確認問題: 価格検索のインデックスには利点だけがありますか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

索引を付けると読む処理と書く処理の両方が変わります。

ヒント2

INSERT時にも索引を維持する必要があるか考えます。

ヒント3

実際の検索計画を見るコマンドの役割も確認してください。

模範解答と理由

いいえ。検索を速くする可能性がありますが、書き込みや容量に負担があり、EXPLAINで利用状況を確認します。

この節の自己採点基準(1点満点)

独立して判定する正答要素

  1. 1点: 検索を速くする可能性がありますが、書き込みや容量に負担があり、EXPLAINで利用状況を確認します。

満点の正答例: いいえ。検索を速くする可能性がありますが、書き込みや容量に負担があり、EXPLAINで利用状況を確認します。

部分点の判定: 正答要素は1つなので部分点はありません。意味が一致すれば1点、異なれば0点です。

誤答・採点ミスの例: 不十分な解答例:「よく分からないが、そのまま進めればよい」。正答条件「検索を速くする可能性がありますが、書き込みや容量に負担があり、EXPLAINで利用状況を確認します」を示していないので0点です。

合格条件:1/1点。 正答の言い換えは認めます。

復習先: この節「12. インデックスとEXPLAINの入門」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

13. トランザクションとCOMMIT・ROLLBACK

注文を登録して在庫を減らす処理では、片方だけ成功するとデータが不整合になります。そこで複数の変更を「すべて成功するか、すべて取り消すか」という単位にまとめるトランザクションを使用します。

START TRANSACTION で開始し、正常なら COMMIT で確定します。途中で失敗したときは ROLLBACK で取り消します。トランザクションの学習ではMySQLのInnoDBテーブルを使用します。

START TRANSACTION;
UPDATE products SET stock = stock - 2 WHERE id = 1 AND stock >= 2;
SELECT id, stock FROM products WHERE id = 1;
ROLLBACK;

この例ではROLLBACKするため、保存済みの在庫数は変更されません。なおDDL(CREATE TABLE等)の多くは暗黙のコミットを伴うため、一般的な更新SQLと同じ感覚でROLLBACKできるとは限りません。

理解を深める:トランザクションは複数のDB操作を一まとまりとして扱う

注文では「在庫を減らす」と「注文履歴を記録する」の両方が成立しなければなりません。途中で履歴保存に失敗したのに在庫だけ減るとデータが矛盾します。そこで一連の操作をトランザクションとしてまとめます。

START TRANSACTION;
UPDATE products SET stock = stock - 2 WHERE id = 1 AND stock >= 2;
-- ここで更新件数が1件であることを確認する必要があります
-- 次の注文INSERTなども同じトランザクション内で実施します
ROLLBACK;

ROLLBACK すると未確定の変更を取り消します。COMMIT すると確定します。トランザクションがあっても、在庫が足りたかの確認は自動では行われません。 更新件数を確認する必要があります。

また、各文がトランザクション対応のテーブルで実行されていることも前提です。

理解を深める:トランザクションの失敗を再現する

START TRANSACTION;
UPDATE sql_practice_products SET price = 999 WHERE id = 1;
SELECT price FROM sql_practice_products WHERE id = 1;
ROLLBACK;
SELECT price FROM sql_practice_products WHERE id = 1;

1回目のSELECTでは999、ROLLBACK後は100が期待値です。ROLLBACK はトランザクション中の確定していない変更を取り消します。

MySQLのテーブルがInnoDBなどのトランザクション対応エンジンであることを前提とします。COMMIT を実行すると変更は確定します。

この節の独学チェック:13. トランザクションとCOMMIT・ROLLBACK

確認問題: START TRANSACTION後にUPDATEし、ROLLBACKしたらどうなりますか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

更新操作の前後を未確定と確定に分けます。

ヒント2

トランザクションをサポートする表かどうか考えましょう。

ヒント3

途中でDDLがある場合と単純なUPDATEだけの場合を区別します。

模範解答と理由

InnoDBなどトランザクションをサポートするテーブルへの未コミットのUPDATEは、通常ROLLBACKで取り消されます。ただしDDLのように暗黙コミットが発生する命令や、トランザクション非対応のテーブルには同じ説明を適用できません。

この節の自己採点基準(2点満点)

独立して判定する正答要素

  1. 1点: InnoDBなどトランザクションをサポートするテーブルへの未コミットのUPDATEは、通常ROLLBACKで取り消されます。
  2. 1点: ただしDDLのように暗黙コミットが発生する命令や、トランザクション非対応のテーブルには同じ説明を適用できません。

満点の正答例: InnoDBなどトランザクションをサポートするテーブルへの未コミットのUPDATEは、通常ROLLBACKで取り消されます。ただしDDLのように暗黙コミットが発生する命令や、トランザクション非対応のテーブルには同じ説明を適用できません。

部分点の判定: 部分正答例:「InnoDBなどトランザクションをサポートするテーブルへの未コミットのUPDATEは、通常ROLLBACKで取り消されます」。この記述だけなら1点で、残る正答要素は未達です。

誤答・採点ミスの例: 不十分な解答例:「InnoDBなどトランザクションをサポートするテーブルへの未コミットのUPDATEは、通常ROLLBACKで取り消されます」。他の必須要素を欠いたまま満点と判定するのは誤りです。

合格条件:2/2点。 正答の言い換えは認めます。

復習先: この節「13. トランザクションとCOMMIT・ROLLBACK」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

図解:トランザクションの分岐

トランザクションの分岐

図の読み方:同一トランザクション内の未確定変更はROLLBACKで取り消せます。

14. JDBC:JavaからDBへ接続する仕組み

JDBCはJavaプログラムからデータベースにアクセスするための標準的なAPIです。APIとは、他の機能をプログラムから利用するための窓口です。

MySQL専用のJDBCドライバーであるConnector/JをMavenに追加すると、JavaがMySQLと通信できるようになります。教材にある pom.xml はドライバーを宣言しています。

最初の依存ライブラリの取得にはインターネット接続が必要ですが、学習中のDBとプログラムの実行はローカルPCで完結します。

URL jdbc:mysql://localhost:3306/training_db の localhost は自分のPC、3306は接続ポート、最後はデータベース名です。

接続情報は環境変数 TRAINING_DB_USER、TRAINING_DB_PASSWORD から取得します。プログラムへパスワードを直書きしません。

$env:TRAINING_DB_USER = "training_user"
$env:TRAINING_DB_PASSWORD = "ここに各自のパスワード"

PowerShellで設定した環境変数はそのPowerShellプロセスと子プロセスに継承されます。

Eclipseを既に起動していた場合、Eclipseの「実行構成」から環境変数を設定するか、設定後にEclipseを起動してください。

この節の独学チェック:14. JDBC:JavaからDBへ接続する仕組み

確認問題: JDBCの役割を一言で説明してください。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

JDBCはSQL文そのものの名前ではありません。

ヒント2

JavaのコードからDBへ依頼を送る経路を描きましょう。

ヒント3

接続・SQL実行・結果取得の3動作に共通する仕組みを答えます。

模範解答と理由

JavaアプリケーションからDBへ接続し、SQLを実行して結果を受け取るための標準APIです。

この節の自己採点基準(1点満点)

独立して判定する正答要素

  1. 1点: JavaアプリケーションからDBへ接続し、SQLを実行して結果を受け取るための標準APIです。

満点の正答例: JavaアプリケーションからDBへ接続し、SQLを実行して結果を受け取るための標準APIです。

部分点の判定: 正答要素は1つなので部分点はありません。意味が一致すれば1点、異なれば0点です。

誤答・採点ミスの例: 不十分な解答例:「よく分からないが、そのまま進めればよい」。正答条件「JavaアプリケーションからDBへ接続し、SQLを実行して結果を受け取るための標準APIです」を示していないので0点です。

合格条件:1/1点。 正答の言い換えは認めます。

復習先: この節「14. JDBC:JavaからDBへ接続する仕組み」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

15. Connection・PreparedStatement・ResultSet

JDBCでは Connection がDBとの接続、PreparedStatement がパラメーター付きSQLの実行準備、ResultSet が検索結果を表します。? は後から値を設定する場所です。

利用者の入力をSQL文字列と直接連結するとSQLインジェクションという重大な問題の原因になります。PreparedStatement のプレースホルダーを使い、setInt や setString で値を渡します。

テーブル名などSQLの構造は ? では置き換えられないため、利用者入力を自由にSQL構造へ埋め込まないでください。try-with-resources を使うと、処理終了時に接続などを閉じられます。

String sql = "SELECT id, name, price, stock FROM products WHERE price >= ? ORDER BY id";
try (Connection con = Db.open();
     PreparedStatement ps = con.prepareStatement(sql)) {
    ps.setBigDecimal(1, new BigDecimal("100"));
    try (ResultSet rs = ps.executeQuery()) {
        while (rs.next()) {
            System.out.println(rs.getInt("id") + " " + rs.getString("name"));
        }
    }
}

実行できる完全なコードは examples/05_database/ を参照してください。

理解を深める:JDBCの役割とSQLインジェクション

JavaからSQLを実行する窓口がJDBCです。Connection は接続、PreparedStatement は値を安全に渡せるSQL文、ResultSet は検索結果を順番に読むものです。

String sql = "SELECT name FROM products WHERE id = ?";
try (PreparedStatement ps = connection.prepareStatement(sql)) {
    ps.setLong(1, 1L);
    try (ResultSet rs = ps.executeQuery()) {
        if (rs.next()) {
            System.out.println(rs.getString("name"));
        }
    }
}

? は値を渡す場所(プレースホルダー)です。setLong(1, 1L) は1番目の ? に数値1を渡します。値を文字列連結でSQL本文に埋め込むより、SQLインジェクションを防ぎやすくなります。

テーブル名や列名そのものは通常プレースホルダーにできないため、アプリ側で固定するか許可リストで選びます。

この節の独学チェック:15. Connection・PreparedStatement・ResultSet

確認問題: PreparedStatementで ? に値を設定する理由は何ですか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

SQL文字列へ利用者入力を連結した場合を想像します。

ヒント2

?に値を設定する操作とSQLの構造を分離して考えます。

ヒント3

特殊文字を含む値でもSQLの意味が変わらない理由を探してください。

模範解答と理由

SQL文と値を分離して安全に扱い、SQLインジェクションを防ぐためです。値の個数や型を合わせます。

この節の自己採点基準(2点満点)

独立して判定する正答要素

  1. 1点: SQL文と値を分離して安全に扱い、SQLインジェクションを防ぐためです。
  2. 1点: 値の個数や型を合わせます。

満点の正答例: SQL文と値を分離して安全に扱い、SQLインジェクションを防ぐためです。値の個数や型を合わせます。

部分点の判定: 部分正答例:「SQL文と値を分離して安全に扱い、SQLインジェクションを防ぐためです」。この記述だけなら1点で、残る正答要素は未達です。

誤答・採点ミスの例: 不十分な解答例:「SQL文と値を分離して安全に扱い、SQLインジェクションを防ぐためです」。他の必須要素を欠いたまま満点と判定するのは誤りです。

合格条件:2/2点。 正答の言い換えは認めます。

復習先: この節「15. Connection・PreparedStatement・ResultSet」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

図解:JDBCによるDBアクセス

JDBCによるDBアクセス

図の読み方:PreparedStatementでSQLを安全に実行し、SELECTの結果をResultSetで取得します。

16. JDBCでの登録・更新・削除

SELECTには executeQuery() を使用し、INSERT/UPDATE/DELETEには executeUpdate() を使用します。戻り値は影響を受けた行数を表します。

例えば在庫を更新したのに0件なら、指定IDが存在しないなどを疑えます。登録後に採番されたIDが必要な場合は自動採番キーを取得する方法があります。今回のサンプルではまず戻り件数を確認し、SQLの対象が予想通りかを学びます。

価格には BigDecimal を使用します。金額を double で扱うと二進数表現による小さな丸め誤差が発生する場合があるためです。

この節の独学チェック:16. JDBCでの登録・更新・削除

確認問題: INSERT/UPDATE/DELETEでexecuteUpdateが返す数値は何ですか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

executeQueryとexecuteUpdateの用途を比べましょう。

ヒント2

3行に対するUPDATEが成功したと仮定します。

ヒント3

戻るのはデータ本体か、操作結果を表す整数かを判定します。

模範解答と理由

通常は影響を受けた行数です。検索結果の行そのものを返すわけではありません。

この節の自己採点基準(2点満点)

独立して判定する正答要素

  1. 1点: 通常は影響を受けた行数です。
  2. 1点: 検索結果の行そのものを返すわけではありません。

満点の正答例: 通常は影響を受けた行数です。検索結果の行そのものを返すわけではありません。

部分点の判定: 部分正答例:「通常は影響を受けた行数です」。この記述だけなら1点で、残る正答要素は未達です。

誤答・採点ミスの例: 不十分な解答例:「通常は影響を受けた行数です」。他の必須要素を欠いたまま満点と判定するのは誤りです。

合格条件:2/2点。 正答の言い換えは認めます。

復習先: この節「16. JDBCでの登録・更新・削除」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

17. JDBCでのトランザクション

JDBCでは Connection#setAutoCommit(false) で自動コミットを無効にし、commit() で確定、rollback() で取消しできます。

途中で例外が発生したときはROLLBACKし、必要なら例外を呼び出し元に伝えます。

商品在庫を減らす処理では UPDATE products SET stock = stock - ? WHERE id = ? AND stock >= ? とし、更新結果が1件かどうかを確認します。

0件なら在庫不足または商品が存在しない可能性があります。教材の OrderService は商品在庫の更新と注文レコード作成を同じトランザクションで実行します。

業務では同時実行や再試行、ロックなどの追加検討も必要ですが、最初に「途中失敗で確定しないこと」を確認してください。

理解を深める:JDBCの安全な書き方とエラー確認

String sql = "SELECT id, name FROM sql_practice_products WHERE price >= ?";
try (Connection connection = DriverManager.getConnection(url, user, password);
     PreparedStatement statement = connection.prepareStatement(sql)) {
    statement.setInt(1, 100);
    try (ResultSet result = statement.executeQuery()) {
        while (result.next()) {
            System.out.println(result.getInt("id") + " " + result.getString("name"));
        }
    }
} catch (SQLException e) {
    System.err.println("SQLの実行に失敗しました。SQLState=" + e.getSQLState());
}

? は値をあとから設定するプレースホルダーであり、setInt(1, 100) は最初のプレースホルダーへ整数100を渡します。入力値をSQL文字列に連結する方法より安全です。

try-with-resources を使うことで、DB接続、SQL実行オブジェクト、結果を順番に閉じます。接続情報は学習用であってもソース管理へパスワードを直接コミットしないでください。

確認表: 正常接続、誤ったパスワード、MySQL停止時、存在しないテーブル、正常な検索をそれぞれ試し、SQLStateと原因を記録します。

DB操作は今回の制作環境では実行できていないため、教材の指示どおりに受講環境で確認する必要があります。

この節の独学チェック:17. JDBCでのトランザクション

確認問題: JDBCでautoCommit(false)にした後、SQLの途中で失敗したら何を実行しますか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

autoCommit(false)の意味を確認してください。

ヒント2

複数の更新の途中で例外が出た状況を想像しましょう。

ヒント3

確定していない変更を元へ戻すConnectionの操作を探してください。

模範解答と理由

接続に対してrollback()を呼び、失敗した一連の更新を取り消します。

この節の自己採点基準(1点満点)

独立して判定する正答要素

  1. 1点: 接続に対してrollback()を呼び、失敗した一連の更新を取り消します。

満点の正答例: 接続に対してrollback()を呼び、失敗した一連の更新を取り消します。

部分点の判定: 正答要素は1つなので部分点はありません。意味が一致すれば1点、異なれば0点です。

誤答・採点ミスの例: 不十分な解答例:「よく分からないが、そのまま進めればよい」。正答条件「接続に対してrollback()を呼び、失敗した一連の更新を取り消します」を示していないので0点です。

合格条件:1/1点。 正答の言い換えは認めます。

復習先: この節「17. JDBCでのトランザクション」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

18. EclipseでMavenプロジェクトを開く

Eclipseを起動し、「ファイル」→「インポート」→「Maven」→「既存Mavenプロジェクト」を選びます。

ルートディレクトリーに examples/05_database を指定すると pom.xml が認識されます。インポート後、プロジェクトを右クリックして「Maven」→「プロジェクトの更新」を実行します。

エラー表示が消えない場合は、JDK 21が選ばれているか、依存ライブラリがダウンロードできたか、Mavenのオフライン設定が有効でないかを確認します。

training.db.Main を「Javaアプリケーションとして実行」すると一覧と追加・更新・削除例を確認できます。ただしこのMainはデータを変更します。

初回は 01_schema.sql、02_seed.sql の順に実行し、内容を理解してからMainを実行してください。

この節の独学チェック:18. EclipseでMavenプロジェクトを開く

確認問題: pom.xmlのあるフォルダーをMavenプロジェクトとして扱う理由は何ですか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

pom.xmlに書かれる情報を確認してください。

ヒント2

Javaファイルだけ取り込む場合とビルド設定を読む場合を比べます。

ヒント3

依存ライブラリとビルド手順を復元するためのファイルを特定しましょう。

模範解答と理由

pom.xmlにビルドと依存ライブラリの設定が書かれているためです。

この節の自己採点基準(1点満点)

独立して判定する正答要素

  1. 1点: pom.xmlにビルドと依存ライブラリの設定が書かれているためです。

満点の正答例: pom.xmlにビルドと依存ライブラリの設定が書かれているためです。

部分点の判定: 正答要素は1つなので部分点はありません。意味が一致すれば1点、異なれば0点です。

誤答・採点ミスの例: 不十分な解答例:「よく分からないが、そのまま進めればよい」。正答条件「pom.xmlにビルドと依存ライブラリの設定が書かれているためです」を示していないので0点です。

合格条件:1/1点。 正答の言い換えは認めます。

復習先: この節「18. EclipseでMavenプロジェクトを開く」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

19. 実務形式の改修演習

既存の ProductDao はID、商品名、価格、在庫数を扱います。課題では商品名による部分一致検索メソッドを追加します。

①仕様を読む、②検索対象を明確にする、③既存のDAOの書き方を調べる、④PreparedStatementで実装する、⑤正常系(該当あり/なし)と異常系を確認する、⑥差分をGitに記録する、という順番で進めます。

実務では要件が曖昧なままコードを書き始めないことが大切です。例えば空文字入力を全件検索とするかエラーとするかは仕様として決めるべき点です。今回の課題では空文字や空白のみはエラーにしてください。

この節の独学チェック:19. 実務形式の改修演習

確認問題: 既存の商品検索に条件を追加する前に、何を確認しますか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

変更前に守るべき動作を明らかにしましょう。

ヒント2

要求された新条件がSQLのどこに影響するか考えます。

ヒント3

仕様・既存結果・変更対象・再テストの4観点で整理します。

模範解答と理由

既存の検索結果、要求される新条件、影響するSQLとJavaコード、回帰テストの対象を確認します。

この節の自己採点基準(3点満点)

独立して判定する正答要素

  1. 1点: 既存の検索結果と新しい要求条件を確認する。
  2. 1点: SQLおよびJavaの変更箇所を調査する。
  3. 1点: 影響する回帰テストを洗い出す。

満点の正答例: 既存の検索結果、要求される新条件、影響するSQLとJavaコード、回帰テストの対象を確認します。

部分点の判定: 部分正答例:「既存の検索結果と新しい要求条件を確認する」。この記述だけなら1点で、残る正答要素は未達です。

誤答・採点ミスの例: 不十分な解答例:「既存の検索結果と新しい要求条件を確認する」。他の必須要素を欠いたまま満点と判定するのは誤りです。

合格条件:3/3点。 正答の言い換えは認めます。

復習先: この節「19. 実務形式の改修演習」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

20. よくあるエラーと調査方法

Access denied for user はユーザー名・パスワード・接続元・権限の不一致が候補です。Communications link failure はサーバー停止、ポート違い、通信の問題が候補です。

Unknown database はDB名の間違い、Table ... doesn't exist はテーブル未作成の可能性があります。

No suitable driver はMaven依存関係やJDBC URLを確認します。外見が似たエラーでも原因は違います。

①エラーメッセージを読む、②操作した内容を再現する、③接続先・資格情報・SQLを順に確認する、④変更は一度に一つだけ行う、という手順を守りましょう。エラー全文を共有するときはパスワードや個人情報を伏せてください。

この節の独学チェック:20. よくあるエラーと調査方法

確認問題: Access deniedとConnection refusedは同じ原因ですか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

認証拒否とTCP接続拒否を区別しましょう。

ヒント2

サーバーまで通信できているかを先に判断します。

ヒント3

ユーザー権限とサーバー起動・ポートを別の原因群に分けます。

模範解答と理由

通常異なります。前者は認証・権限、後者はサーバー停止や接続先・ポートの誤りを疑います。

この節の自己採点基準(2点満点)

独立して判定する正答要素

  1. 1点: Access deniedは認証・権限の問題を疑う。
  2. 1点: Connection refusedはサービス起動・接続先・ポートを疑う。

満点の正答例: 通常異なります。前者は認証・権限、後者はサーバー停止や接続先・ポートの誤りを疑います。

部分点の判定: 部分正答例:「Access deniedは認証・権限の問題を疑う」。この記述だけなら1点で、残る正答要素は未達です。

誤答・採点ミスの例: 不十分な解答例:「Access deniedは認証・権限の問題を疑う」。他の必須要素を欠いたまま満点と判定するのは誤りです。

合格条件:2/2点。 正答の言い換えは認めます。

復習先: この節「20. よくあるエラーと調査方法」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

21. 理解度チェックとまとめ

確認問題:①テーブルの行と列の違いは何ですか。②主キーはなぜ必要ですか。③WHEREを省略したUPDATEには何の危険がありますか。④外部キーはどのような不整合を防ぎますか。

⑤PreparedStatementが重要なのはなぜですか。⑥executeQueryとexecuteUpdateの違いは何ですか。⑦commitとrollbackをどの場面で使用しますか。

⑧Connectionなどを閉じる必要があるのはなぜですか。答えを説明できなければ該当節に戻り、小さなSQLやJavaコードで確かめてください。

次章では、このDBアクセスをSpring BootのWebアプリケーションから利用する入口を学習します。

理解を深める:確認問題

  1. 主キーと外部キーはそれぞれ何を守る仕組みですか。
  2. JOIN で ON を省略するとどのような問題が起こりますか。
  3. 在庫更新が成功し注文登録が失敗した場合、何を行うべきですか。
  4. PreparedStatementを使っても、SQLの列名を利用者入力で直接連結する設計はなぜ危険ですか。

学習内容の確認ポイント

SQLだけでSELECT、INSERT、UPDATE、DELETEを実行し、変更内容を確認できるようになってからJDBCへ進みます。第10章では別DB training_final_db を使用します。

第05章のtraining_dbと表構造が異なるため同じテーブルを上書きしないでください。

学習内容を振り返るための操作確認

この節は、本文の例題や演習が実行できないときに戻るための案内です。最初にファイルの場所と作業中のツールを確認し、コマンドを貼り付ける前に現在のフォルダーを確認してください。

実行する場所と順序

SQLファイルはPowerShellへそのまま貼り付けず、MySQLの mysql> プロンプト内で実行します。mysql -u ... は逆にOSのターミナルで実行します。

成功・失敗の判断

SELECT DATABASE(); と SHOW TABLES; で対象DBを特定し、更新前と更新後の行を記録します。

途中で止まったとき

接続できなければMySQLサービスの起動、ポート、ユーザー、DB名を順に確認します。SQLの実行エラーとOSコマンドのエラーを混同しないでください。

作業記録の書き方

  1. 利用環境(OS、Java、必要なツールのバージョン)を記録します。
  2. 実際に操作したフォルダー、実行コマンド、入力内容を記録します。
  3. 期待した結果と実際の結果を別々に書きます。失敗時にはエラーメッセージの全文を保管します。
  4. 修正を加えた場合は変更箇所を記録し、同じ手順で再確認します。
  5. 成功を確認できていなければ「未確認」と記載し、成功と推測して次へ進まないでください。

実際の入力、実行結果、原因の説明、演習の提出物がそろって初めて章の学習を完了とします。

この節の独学チェック:21. 理解度チェックとまとめ

確認問題: DB章の理解度チェックではどんな結果を自分で確認すべきですか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

SELECT、UPDATE、ROLLBACKで観測する対象は同じでしょうか。

ヒント2

データ行と変更件数を記録する場面を考えましょう。

ヒント3

Javaの取得結果とSQLで直接確かめた状態を突き合わせます。

模範解答と理由

SQLの取得行・更新行数・ロールバック後の値と、JDBC側の結果が一致することを確認します。

この節の自己採点基準(1点満点)

独立して判定する正答要素

  1. 1点: SQLの取得行・更新行数・ロールバック後の値と、JDBC側の結果が一致することを確認します。

満点の正答例: SQLの取得行・更新行数・ロールバック後の値と、JDBC側の結果が一致することを確認します。

部分点の判定: 正答要素は1つなので部分点はありません。意味が一致すれば1点、異なれば0点です。

誤答・採点ミスの例: 不十分な解答例:「よく分からないが、そのまま進めればよい」。正答条件「SQLの取得行・更新行数・ロールバック後の値と、JDBC側の結果が一致することを確認します」を示していないので0点です。

合格条件:1/1点。 正答の言い換えは認めます。

復習先: この節「21. 理解度チェックとまとめ」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。