概要
タイトル通り、SpringBootで作ったJavaアプリケーションからMySQLへ接続してみようと思います。
O/RマッパーにはMyBatisを使用します。※MyBatisとは
実質環境構築してみたの続きに該当しますので、
前提となる環境についてはそちらも参考にしてください。
またもし接続できない場合などございましたら、お気軽にコメントをお願いいたします。
本題
ではここから本題に入っていきましょう。
今回はシンプルに、GETリクエストを送ったらDBの全データをリストで取得してくるAPIを作ります。
テーブル名やテストデータはこちらが入っている前提です。
1. APIを作るための準備をする
1-1. 依存を追加する
前回の環境構築だけでは依存が不足しているので、依存を追加していきましょう。
便利なSpringInitializerを使っていきます。
MySQL、MyBatisに、WebとLombokを追加してGenerate Projectをクリックします。※Lombokとは
ダウンロードできたzipからbuild.gradleの内容をプロジェクトのbuild.gradleにコピペしましょう。
念のためRefreshもしておきます。
無事依存を取り込めました。
1-2. IntelliJのプラグインを設定する
続いてIntelliJ側のプラグインをいじります。
Ctrl + Alt + SでSettingsを開き、Pluginsの下部にある**Browse repositories...**をクリックします。
lombokと検索するとLombok Pluginが出てくると思うので、Installをクリックしてインストールします。
インストールできるとInstallの文字がRestart IntelliJ IDEAに代わってると思うので、クリックして再起動します。
再起動されたらOKです!
これで準備完了です!
ではプログラミングに入っていきましょう!
2. APIを作る
今回はめちゃくちゃシンプルに、コントローラとマッパーだけの構成としてみましょう。(データクラスなどはありますが)
ソースについて深く解説はしない方針としますのでご了承ください。
2-1. Controller周りを作る
@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)
}
}
@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周りを作る
@Mapper // (1)
@Component
public interface UsersMapper {
List<UsersEntity> findUserList(); // (2)
}
@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 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>
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公式を参考にしてください。
これで作成できました!!
あとは実際にAPIにリクエストを送って、DBから値が取れるか試してみましょう!!
3. 実際にリクエストしてみる
リクエスト送信にあたってPostman REST Clientを使用します。
勿論curlでも、その他ツールを使っていただいても大丈夫です。
それではAPIを起動させましょう。IntelliJからGradleタスクのbootRunを選択して起動させます。
URL(http://localhost:8080/get/sample) を指定して、GETメソッドであることを確認したらSendをクリックします。
これでDB操作はいつでもできますね!!
最後に
**「環境さえできていればあっさり作れるじゃないか!」**っていう印象です。
MyBatisはSQLが記述できること、javaとのマッピングが分かりやすいところが個人的に好きです。
XMLを書かなきゃならないところや、JPAのように自動生成機能がないところが嫌がられているようではありますが。。
なんでもそうですが、慣れてしまえば簡単かなと思います!