02. SpringBootからMySQL(MyBatis)へ接続するAPIを作ってみた

# 概要
タイトル通り、SpringBootで作ったJavaアプリケーションからMySQLへ接続してみようと思います。
O/RマッパーにはMyBatisを使用します。※[MyBatisとは](https://qiita.com/supreme0110/items/ce31a506185ccc97693f)

実質[環境構築してみた](https://qiita.com/supreme0110/items/896cfa0349be5eacfed5)の続きに該当しますので、
前提となる環境についてはそちらも参考にしてください。

またもし接続できない場合などございましたら、お気軽にコメントをお願いいたします。

# 本題
ではここから本題に入っていきましょう。
今回はシンプルに、**GETリクエストを送ったらDBの全データをリストで取得してくるAPI**を作ります。
テーブル名やテストデータは[こちら](https://qiita.com/supreme0110/items/896cfa0349be5eacfed5#4-1-db%E3%81%AB%E3%83%86%E3%83%BC%E3%83%96%E3%83%AB%E3%82%92%E4%BD%9C%E3%82%8B)が入っている前提です。

## 1. APIを作るための準備をする
### 1-1. 依存を追加する
前回の環境構築だけでは依存が不足しているので、依存を追加していきましょう。
便利な[SpringInitializer](https://start.spring.io/)を使っていきます。
MySQL、MyBatisに、**WebとLombokを追加**して**Generate Project**をクリックします。※[Lombokとは](https://qiita.com/supreme0110/items/391505da8f4321736421)
![イニシャライザ.png](https://qiita-image-store.s3.amazonaws.com/0/188440/7028695d-8862-1de8-5ce3-74214908a3a3.png)

ダウンロードできたzipからbuild.gradleの内容をプロジェクトのbuild.gradleにコピペしましょう。
念のため**Refresh**もしておきます。
![依存追加.png](https://qiita-image-store.s3.amazonaws.com/0/188440/caf75ac0-eadf-ce9f-cca1-56ad8f1dbfb5.png)

無事依存を取り込めました。

### 1-2. IntelliJのプラグインを設定する
続いてIntelliJ側のプラグインをいじります。
**Ctrl + Alt + S**でSettingsを開き、**Plugins**の下部にある**Browse repositories...**をクリックします。
![プラグイン設定.png](https://qiita-image-store.s3.amazonaws.com/0/188440/2dafd406-7961-0e74-8c5c-b88055d9cded.png)

lombokと検索すると**Lombok Plugin**が出てくると思うので、**Install**をクリックしてインストールします。
![プラグイン設定2.png](https://qiita-image-store.s3.amazonaws.com/0/188440/7e62b2a0-7ff6-1a4d-c9c5-a026206654eb.png)

インストールできると**Install**の文字が**Restart IntelliJ IDEA**に代わってると思うので、クリックして再起動します。
再起動されたらOKです！

これで準備完了です！
ではプログラミングに入っていきましょう！

## 2. APIを作る
今回はめちゃくちゃシンプルに、**コントローラとマッパーだけ**の構成としてみましょう。(データクラスなどはありますが)
ソースについて深く解説はしない方針としますのでご了承ください。
### 2-1. Controller周りを作る

``` java:com.example.sampleapi.controller.SampleController.java
@RestController
@RequiredArgsConstructor
public class SampleController {
    private final UsersMapper usersMapper;  // (1)

    @GetMapping("/get/sample")
    public List<SampleResponse> getSample() {
        List<UsersEntity> usersEntityList = usersMapper.findUserList();  // (2)
        return usersEntityList.stream().map(SampleResponse::create).collect(Collectors.toList());  // (3)
    }
}
```

``` java:com.example.sampleapi.controller.resource.SampleResponse.java
@Value  // (4)
public class SampleResponse {
    private Integer userId;
    private String userName;

    public static SampleResponse create(UsersEntity entity) {  // (5)
        return new SampleResponse(
                entity.getUserId(),
                entity.getUserName()
        );
    }
}
```
簡単な説明です。
(1). `@RequiredArgsConstructor`によって、`final`が付いたフィールドに対して初期値を代入するコンストラクタが自動生成されます。つまり**コンストラクタインジェクション**されているということですね。
(2). `UsersMapper`を呼び出し、DBから取得できたデータをエンティティのリストとして受け取ります。
(3). (2)で受け取ったリストを`SampleResponse`クラスのリストに詰め替える処理行っています。
(4). Lombokの`@Value`によって、全フィールドを初期化するコンストラクタとgetterが自動生成されます。
(5). (3)の処理記述を簡潔にするために、エンティティからレスポンスへ詰め替える処理を切り出しています。

続いてDB接続に関するクラス、インターフェースを作っていきましょう。

### 2-2. Mapper周りを作る
``` java:com.example.sampleapi.mapper.UsersMapper.java
@Mapper  // (1)
@Component
public interface UsersMapper {
    List<UsersEntity> findUserList(); // (2)
}
```

``` java:com.example.sampleapi.mapper.entity.UsersEntity.java
@Data  // (3)
public class UsersEntity {
    private Integer userId;
    private String userName;
}
```

またまた簡単な説明です。
(1). MyBatisのアノテーションである`@Mapper`を付与します。これによってこのクラスがXMLと紐付くマッパーであることを認識します。
(2). 実装したいメソッドを宣言します。**メソッド名が後述するXMLのid属性とマッピングされ、対応するSQLが実行**されます。
(3). Lombokが提供する`@Data`アノテーションです。これにより全フィールドに対してsetter、getterが自動生成されます。

ここまでやってみて、
**「テーブルのカラム名はスネークケースなのに、エンティティのフィールドはキャメルケースでマッピングできるの？」**
と思ったあなた。
あと少しだけ設定があるのでこのまま進めてください。
最後にXMLファイルを作り、application.ymlに簡単な設定を入れ込んで完了です。

### 2-3. XML作成とapplication.ymlによる設定
``` xml:resources.mapper.Users.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.sampleapi.mapper.UsersMapper">  <!-- (1) -->
    <select id="findUserList" resultType="com.example.sampleapi.mapper.entity.UsersEntity">  <!-- (2) -->
        SELECT
            USER_ID,
            USER_NAME
        FROM
            USERS
    </select>
</mapper>
```

``` yml:resources.application.yml
spring:  # ここはDBの接続情報を定義しているだけなので今回は関係ありません
  datasource:
    url: jdbc:mysql://localhost/sample_db
    username: root
    password: dummy

mybatis:
  mapperLocations: classpath*:/mapper/*.xml  # (3)
  configuration:
    mapUnderscoreToCamelCase: true  # (4)
```
最後の簡単な説明です。
(1). `namespace`属性で`@Mapper`が付与されているクラスのパスを指定します。これにより、このXMLファイルがどのJavaインターフェースとマッピングされているかを認識させます。
(2). 先述した`UsersMapper.findUserList()`とマッピングさせるために、`id`属性に`findUserList`と記述します。また戻り値を指定する必要があるため、`resultType`属性に`UsersEntity`クラスのパスを書きます。
(3). 今回のようにMapperインターフェースとXMLファイルが別のパッケージに存在するような構成にしたい場合は、`mapperLocations`を指定することでXMLを正しく読み込むようにできます。
(4). 先述した**スネークケースのカラム名と、キャメルケースで書かれたエンティティのフィールドを自動でマッピングしてくれる便利な機能**です。デフォルトが`false`になっているため、`true`にしてあげましょう。

これ以外にもたくさん便利な設定項目が存在します。[MyBatis公式](http://www.mybatis.org/mybatis-3/ja/configuration.html#settings)を参考にしてください。

これで作成できました！！
あとは実際にAPIにリクエストを送って、DBから値が取れるか試してみましょう！！

## 3. 実際にリクエストしてみる
リクエスト送信にあたって[Postman REST Client](https://chrome.google.com/webstore/detail/tabbed-postman-rest-clien/coohjcphdfgbiolnekdpbcijmhambjff/related)を使用します。
勿論curlでも、その他ツールを使っていただいても大丈夫です。

それではAPIを起動させましょう。IntelliJからGradleタスクの**bootRun**を選択して起動させます。

URL(http://localhost:8080/get/sample) を指定して、GETメソッドであることを確認したら**Send**をクリックします。
![postman1.png](https://qiita-image-store.s3.amazonaws.com/0/188440/3df27c8e-c43f-90e0-f7d6-9596b5489370.png)

無事値が取れたことが確認できると思います！
![postman2.png](https://qiita-image-store.s3.amazonaws.com/0/188440/a6bbc855-a63b-5cec-aef0-564189dbc05e.png)

**これでDB操作はいつでもできますね！！**

# 最後に
**「環境さえできていればあっさり作れるじゃないか！」**っていう印象です。

**MyBatisはSQLが記述できること、javaとのマッピングが分かりやすいところ**が個人的に好きです。
XMLを書かなきゃならないところや、JPAのように自動生成機能がないところが嫌がられているようではありますが。。

なんでもそうですが、慣れてしまえば簡単かなと思います！