Javaからのデータベース操作基礎（初心者メモ）

## JDBCとは
javaプログラムとRDBMS（リレーショナルデータベース管理システム。MySQLなど）の仲介を行うプログラム部品のこと。
javaプログラムからDBへの接続、SQLの実行、データの取得などを行う手段を提供する。
javaプログラムがRDBMSを扱う際は、JDBCに含まれる「**JDBC API**と**JDBCドライバ**」を介して行われる。
### JDBC API
- JDBC APIは**Java標準ライブラリ**に含まれている
- RDBMSを標準化された方法で操作が可能
- パッケージ「java.sql」「javax.sql」に含まれるクラスを使用してDB接続、SQLの実行を行うことが可能
### JDBCドライバ
- RDBMSに接続して処理を実行する
- Oracle、MySQLなどRDBMSごとに異なるJDBCドライバが存在しており、各RDBMSの開発元が提供している
### JDBCAPIとJDBCドライバで分かれている理由
JDBCはjavaプログラムからDBを操作する上でRDBMSの違いを吸収する役割をしている。
例えば、RDBMSがMySQLの場合、MySQL用のJDBCドライバになる。
そうする事で、javaプログラムの標準的なデータベース操作を変更せずにRDBMSを変更できることとなる。

:::note info
JDBCの利点
- 異なるRDBMSに対して標準化された方法で操作可能
- プログラムを変更せずにRDBMSの変更に対応できる
（JDBCドライバの変更）
:::

※MySQLのJDBCドライバは、MySQL Connector/Jを使用する

## 開発環境構築
### JavaでのDB利用
#### DB基本
DBeaver,MySQL Connector/J→SQL→MySQL
#### Java
Java,MySQL Connector/J→SQL→MySQL

**Pleiades**に**Java(JDK)**と**eclipse**が含まれており、JDBCAPIを含むJava標準ライブラリを含む。

【流れ】
1. MySQLのインストール
2. JDBCドライバのインストール
3. DBeaverのインストール
4. 管理者アカウント(root)で接続
5. スキーマ（DB）作成
6. ユーザ作成
7. アクセス権限付与（ユーザがDBへのアクセスを可能とする）
8. ユーザアカウントで接続
9. テーブル作成・制約作成
10. レコード追加

## MySQL基礎メモ
DBが存在する場合は削除
```
DROP DATABASE IF EXSIS DB名
```
データベース作成(5)
```
CREATE DATABASE データベース名;
```

DB照合順序を指定する：COLLATE
```
CREATE DATABASE データベース名 COLLATE 照合順序;
```
例えば、よく見かける「COLLATE utf8_general_ci」という場合。文字コードは「utf8」で、言語は多言語を示す「general」、文字列の比較方法は大文字と小文字が区別されない 「ci」であるということを意味します。

※参照
[MySQLの文字コード（characterset）と照合順序（collation）についてとその設定](https://qiita.com/ryouzi/items/c40c32a8772602f2f8d3)

```
CREATE DATABASE データベース名 CHARACTER SET utf8 COLLATE utf8mb4_general_ci;
```
上記SQL解説
- CHARACTER SET utf8
文字コードをutf8に設定
- COLLATE utf8mb4_general_ci
照合順序を設定
照合順序（collation）とは、データベース内のデータの文字同士を比較するときのルールのこと。
この設定により、「大文字のA」と「小文字のa」、「全角のア」と「半角のｱ」を区別するかどうかなどの挙動が変わってきます。

MySQLの文字コードのutf8は1～3バイトまでの対応となっており、絵文字などが保存できません。
絵文字などを保存するには、MySQLの文字コードをutf8mb4にしなければなりません。
これからMySQLサーバーを新しく構築する際には、MySQLの文字コードはutf8mb4にしておくことが良いかと思います。

### DBユーザ作成(6)
```
CREATE USER IF NOT EXISTS shop_user IDENTIFIED BY 'pass';
```
- CREATE USER IF NOT EXISTS ユーザ名
ユーザーがまだ存在しない場合にのみ作成するという意味のステートメント
- INDENTIFIED BY
パスワードの割り当て
### 権限付与(7)
```
GRANT ALL PRIVILEGES ON pc_shop_db.* TO shop_user;
```
- GRANT ALL PRIVILEGES ON データベース名.* TO ユーザ名
ONで指定したデータベースの全テーブルに対して、TOで指定したユーザーにフルアクセス権を付与する

※参照
[MySQlのホスト名とは？](https://oreno-it3.info/archives/274)
MySQLのホスト名とは、MySQLデータベースが稼働しているサーバーの名前のことを指します。サーバー名、データベースサーバー名とも呼ばれます。

**テーブルとデータ作成は割愛（SQL入門ドリルで別途復習する）**

## eclipseでJDBC（mySQL）ドライバ設定
eclipseで新規プロジェクトを作成
→プロジェクト名を右クリック
→ビルドパス
→ビルドパスの構成
→ライブラリタブを選択
→モジュールパスを選択し、右側の「外部JARを追加」を押下
→C:\Program Files (x86)\MySQL\Connector J 8.0\mysql-connector-java-8.0.26を開く
→適用して閉じる

### DB操作の流れ
1.　接続
2. SQLステートメント準備
3. SQLステートメント実行
4. 結果の利用
5. 切断

#### 【1.接続】
接続を表すオブジェクトを取得
Connection con
= DriverManager.getConnection(...);
#### 【2.SQLステートメント準備】

:::note warn
ユーザの入力によりsql文の条件を決めたい場合は、悪意のあるsql実行を防ぐためにもプレースホルダー（?）が使えるPreparedStatement（プリコンパイルされたsql文を示すオブジェクト）を使用する。
また、ステートメント準備段階でsql構文のチェックを行ってくれるため、処理効率が上がる。
使い方に関しては別途サイトを参照。
:::

Statement stmt
=**con**.createStatement();
#### 【3.SQLステートメント実行】
ResultSet res
= **stmt**.executeQuery(sql);
#### 【4.結果の利用】
ResultSetオブジェクトを使用する
#### 【5.切断】
接続を切断する
**try-with-resources**にて自動切断
```
try(リソース解放が必要なオブジェクトの初期化){
}catch(例外クラス e){
~~~
}
```
- Java7から導入された機能で、javaが自動的にリソース解放を行う構文
- try()内で、リソース解放が必要なオブジェクトの初期化を行う
- AutoClosableインターフェース又はClosableインターフェースを実装したオブジェクトの初期化のみ、try()内に書ける
 (java.io.Closeableを実装するすべてのオブジェクトを含む、java.lang.AutoCloseableを実装するすべてのオブジェクトをリソースとして使用できます。)
- この構文を抜けるときに、リソースの解放を行うclose()メソッドが自動的に呼ばれる

※参照
[try-with-resourcesとAutoCloseable](https://qiita.com/Mk-4000/items/45829318755808bb4fa3)
**AutoCloseableとCloseableについて**
AutoCloseableは例外発生時にExceptionをスローするが、CloseableはIOExceptionをスローする。

:::note warn
補足
IOExceptionの方がより具体的なエラーについて処理できる。
Exceptionだと「具体的にどんなエラーが起きたのか」がわからないが、IOExceptionだと「入出力でエラーが起きた」というのがすぐにわかる。らしい
:::

【SELECT実行】
例
DB操作の流れ1~3はtry-with-resourcesのtryの中に記載する
```
String sql = "SELECt user_id, user_name, birth_day FROM m_user ";
try(Connection con DriverManager.getConnection(url,user,password);
    Statement stmt = con.createStatement();
        ResultSet res = stmt.executeQuery(sql) ) {
    ~~
} catch (SQLException e){
    System.out.println("\nエラーが発生しました。");
}
```
【next()メソッド】
- 次の行があればカーソルを進める
- 戻り値は、次の行があればtrue、なければfalse
【結果データの取得】
現在のカーソル行から所定のメソッドでデータを取得する
- getString("フィールド名")、getInt("フィールド名")などのメソッドを呼び出してデータ取得
```
// 取得例
String name = res.getString("user_name");
```

<table>
  <caption>ResultSetのデータ取得メソッド抜粋</caption>
  <thead>
    <tr>
      <th>メソッド</th> <th>取得値のデータ型</th>
    </tr>
  </thead>
  <tr>
    <td> getString("フィールド名") </td> <td>String</td>
  </tr>
  <tr>
    <td> getInt("フィールド名") </td> <td>int</td>
  </tr>
  <tr>
    <td> getDouble("フィールド名") </td> <td>double</td>
  <tr>
    <td> getDate("フィールド名") </td> <td>java.sql.Date</td>
</table>



**その他～eclipse便利機能～**
- ctrl + Shift + O
必要なクラスを自動インポート
- ctrl + F11
前回の実行の再実行
- ctrl + {
ソースの表示を左右に分割

**～参照サイト～**
[PreparedStatementを利用したデータベースアクセスの基本構文](https://kanda-it-school-kensyu.com/java-jdbc-contents/jj_ch03/jj_0302/)

[【Scanner】.next()と.nextLine()の違いと、初心者向けのScannerの解説](https://qiita.com/hot-mock/items/08894e027cf0f8a0cb23)

[formatメソッド](https://java-code.jp/173)