# Question07 - 接続・切断処理の共通部品化 本資料の練習問題は、複数のプログラミング言語(Java / PHP / C# / Python)で共通して利用できるよう記述されています。使用するデータベース接続の仕組み(JDBC、PDO、ADO.NET、DB-API 2.0準拠のドライバ など)やSQLへのパラメータの指定方法、自動採番された値の取得方法など、言語・環境固有の仕様に基づき、問題文の表現をご使用の環境の仕様に適宜読み替えて進めてください。 [共通の前提](../00.共通前提.md)を参照してください。 ## この問題のねらい - データベースへの接続・切断や、後処理のクローズ処理など、複数のプログラムで共通して必要になる処理を、再利用可能な部品としてまとめられること - 既に作成したプログラムを、入力と出力(動作)を変えずに、共通部品を使う形に書き直せること これまでの問題(`Question01`〜`Question05`)では、プログラムごとにデータベースへの接続・切断の処理を毎回自分で実装してきました。この問題では、それらの共通する処理を1つの部品にまとめ、以前の問題で作成したプログラムを、その部品を使う形に書き直します。 扱うSQLや入出力は以前の問題と同じです。新しい処理を覚えるのではなく、**書き直す前と同じ入力を与えて、同じ出力になること**を確認しながら進めてください。 以下の設問1で作成する共通部品は、設問2・3でもそのまま使用します。 ## ファイル名・フォルダ構成 - 設問ごとに1つのフォルダを作成し、そのフォルダの直下にプログラムのファイルを配置すること。 - フォルダ名は、設問番号に対応した連番(`question01`、`question02`、…)とすること(全言語共通・小文字)。 - ファイル名は、設問番号に対応した連番(`Question01`、`Question02`、…)を基本とし、言語の慣習に合わせて次のとおりとすること。 - 本問題(Question07-ConnectionUtility)の構成は次のとおり。 ``` Question07-ConnectionUtility/ ├── question01/       ← 設問1 │ ├── Question01.<拡張子> │ └── common/ │ └── DbUtil.<拡張子> ← 共通部品 ├── question02/       ← 設問2 │ ├── Question02.<拡張子> │ └── common/ │ └── DbUtil.<拡張子> ← 設問1と同じ内容 └── question03/       ← 設問3 ├── Question03.<拡張子> └── common/ └── DbUtil.<拡張子> ← 設問1と同じ内容 ``` - Java: `Question01.java`(公開クラス名もファイル名と同じ `Question01` とする) - C#: `Question01.cs` - PHP: `Question01.php` - Python: `question01.py`(モジュール名は小文字とする慣習のため、ファイル名のみ小文字) - 上記ツリー中の `Question01.<拡張子>` は、使用する言語に応じて上記のファイル名に読み替えること。 - プロジェクトファイルが必要な場合など、言語・開発環境の規則上やむを得ない場合は、その規則を優先してよい。その場合も、設問ごとのフォルダ分けと連番の命名は維持すること。 - 共通部品は、各設問のフォルダの中に `common` フォルダを作成し、その中に配置すること。共通部品のファイル名は、言語の慣習に合わせて次のとおりとすること(クラス名を付ける言語では、クラス名も `DbUtil` とする)。 | 部品 | フォルダ | Java | C# | PHP | Python | | --- | --- | --- | --- | --- | --- | | 共通部品(接続・切断) | `common` | `DbUtil.java` | `DbUtil.cs` | `DbUtil.php` | `db_util.py` | - 共通部品は設問2・3でも使用するため、各フォルダ単独で実行できるよう、設問2・3のフォルダにも設問1と同じ内容の `common` フォルダを配置すること。 --- ## 設問1 ### 共通部品の作成 次の3つの処理を持つ、データベース接続用の共通部品(`common` フォルダの `DbUtil`。ファイル名は「ファイル名・フォルダ構成」を参照)を作成してください(以降の設問でも、この共通部品をそのまま使用します。内容は変更しないものとします)。 1. **接続を取得する処理**:共通の前提のデータベースに接続し、接続を表す値を返す 2. **ステートメントをクローズする処理**:SQL実行に使用した値(ステートメント)を受け取り、値が存在する場合にクローズする 3. **接続を切断する処理**:接続を表す値を受け取り、値が存在する場合に切断する - 補足: 使用する言語に、ステートメントに相当する値を明示的にクローズする標準的な手段がない場合は、後始末に相当する処理(結果セットの解放や、変数への `null` の代入など)で代用してよい ### 書き直すプログラム `Question01`の設問1で作成したプログラム(部署テーブルの全件を部署IDの昇順で出力するプログラム)を、作成した共通部品を使う形に書き直してください。 ### 要件 - データベースへの接続・ステートメントのクローズ・接続の切断は、すべて共通部品を経由して行い、書き直したプログラムの中には接続・切断の処理を直接記述しないこと - 入力と出力は、書き直す前と同じとすること。具体的には次のとおり - 部署テーブルから全件のデータ(部署ID・部署名)を取得し、部署IDの昇順で、1件につき1行、部署IDと部署名をタブ区切りで出力する ### 動作確認 書き直す前と同じ出力になることを確認してください(`Question01`の設問1の実行例と同じです)。 ``` 1 営業部 2 人事部 3 開発部 4 東京支店 5 大阪支店 ``` --- ## 設問2 `Question02`の設問1で作成したプログラム(標準入力から受け取った部署IDに一致する部署のデータを出力するプログラム)を、設問1で作成した共通部品を使う形に書き直してください。 ### 要件 - データベースへの接続・ステートメントのクローズ・接続の切断は、すべて設問1で作成した共通部品を経由して行い、書き直したプログラムの中には接続・切断の処理を直接記述しないこと - 入力と出力は、書き直す前と同じとすること。具体的には次のとおり 1. 次の処理を、有効な入力が得られるまで繰り返す 1. 「検索する部署IDを入力してください」と表示する 2. 標準入力から1行分のテキストを読み込む 3. 読み込んだ内容が整数として解釈できない場合、「数値を入力してください」と表示し、手順1に戻る 4. 整数として解釈できた場合、その値を部署IDとして繰り返し処理を終了する 2. 確定した部署IDを使って、部署テーブルから一致するデータを検索する。この際、SQLに値を直接埋め込むのではなく、パラメータとして値を渡す仕組みを使用する 3. 検索結果が存在する場合、その部署ID・部署名をタブ区切りで出力する 4. 検索結果が存在しない場合、「一致する部署は見つかりませんでした」と出力する ### 動作確認 書き直す前と同じ入力を与え、同じ出力になることを確認してください(`Question02`の設問1の実行例と同じです)。 - 入力が `2` の場合 - 出力:`2 人事部` - 入力が `99`(存在しない部署ID)の場合 - 出力:`一致する部署は見つかりませんでした` - 入力が `abc`(数値でない)の場合 - 出力:`数値を入力してください`(その後、再度入力を促す) --- ## 設問3 `Question04`の設問1で作成したプログラム(標準入力から受け取った部署IDの部署名を更新するプログラム)を、設問1で作成した共通部品を使う形に書き直してください。 ### 要件 - データベースへの接続・ステートメントのクローズ・接続の切断は、すべて設問1で作成した共通部品を経由して行い、書き直したプログラムの中には接続・切断の処理を直接記述しないこと - 入力と出力は、書き直す前と同じとすること。具体的には次のとおり - 「更新対象の部署IDを入力してください」と表示して標準入力から部署IDを読み込み、続けて「新しい部署名を入力してください」と表示して標準入力から新しい部署名を読み込む - 部署名の更新には、SQLに値を直接埋め込むのではなく、パラメータとして値を渡す仕組みを使用する - 更新の結果、実際に更新された件数を確認し、次のとおり出力する - 1件以上更新された場合:「更新完了」 - 該当する部署IDが存在せず、1件も更新されなかった場合:「一致する部署は見つかりませんでした」 - 更新完了の出力に続けて、「確認のため、検索する部署IDを入力してください」と表示し、標準入力から部署IDを読み込んだうえで、その部署IDに一致する部署のデータを部署テーブルから検索し、検索結果(部署ID・部署名)をタブ区切りで出力する ### 動作確認 書き直す前と同じ入力を与え、同じ出力になることを確認してください(`Question04`の設問1の実行例と同じです)。 - 「更新対象の部署IDを入力してください」に対して `2`、「新しい部署名を入力してください」に対して `人材開発部` と入力した場合 - 出力:`更新完了` - 続けて「確認のため、検索する部署IDを入力してください」と表示された後に `2` と入力した場合 - 出力:`2 人材開発部` - 「更新対象の部署IDを入力してください」に対して `99`(存在しない部署ID)、「新しい部署名を入力してください」に対して `広報部` と入力した場合 - 出力:`一致する部署は見つかりませんでした`