山崎屋の技術メモ

IT業界で働く中でテクノロジーを愛するSIerのシステムエンジニア👨‍💻 | AndroidとWebアプリの二刀流🧙‍♂️ | コードの裏にあるストーリーを綴るブログ執筆者✍️ | 日々進化するデジタル世界で学び続ける探究者🚀 | #TechLover #CodeArtisan、気になること、メモしておきたいことを書いていきます。

Spring boot + myBatis で DB 接続する簡単な Web アプリ

前回は Spring が提供する JdbcTemplate を用いて DB アクセスする Web アプリの開発を行いました。

www.shookuro.com


小さなアプリなら JdbcTemplate で十分ですが、実際のプロジェクトでは、そうもいきません。今回はシンプルな O/R マッパーである MyBatis を使用して、入門編として簡単な Web アプリを作成したいと思います。

開発環境は STS 3.9.0。DB は PostgreSQL 9.5.3 を使用します。

インストールはこちらから。

Spring Tool Suite ( STS )インストール - 山崎屋の技術メモ
WindowsにPostgreSQLをインストール - 山崎屋の技術メモ

MyBatis とは

シンプルな O/R マッパーです。単純に SQL の結果をオブジェクトのメンバー変数に詰め替えてくれます。SQL を書いて開発ができるところが好きです。

SQL の基本を抑えていれば、学習コストは非常に低いです。

MyBatis - Wikipedia
公式ページ

「SQL を書かなくて良い」とかいう O/R マッパーはたいてい使い辛い(個人の感想です。)し、学習コストが高いです。たぶん私が使いこなせていないだけなのですが、「SQL 書かせてくれよ~。SQL 書いたほうが早いよ~。」といいたくなります(個人の感想です。)。

テーブルの準備

前回とまったく同じテーブルとデータを使用します。

postgres=# \d
           リレーションの一覧
 スキーマ |  名前  |    型    |  所有者
----------+--------+----------+----------
 public   | fruits | テーブル | postgres
(1 行)


postgres=# select * from fruits;
   name
-----------
 apple
 orange
 pineapple
(3 行)

プロジェクトの作成

メニューの File → New → Spring Stater Project を選択します。

1ページ目は、パッケージとかプロジェクト名とか適当に入力します。

次のページの依存関係の設定では「Web」、「Tymeleaf」、「PostgreSQL」、「JDBC」、「MyBatis」にチェックを入れます。

Finish をクリックすると空のプロジェクトが作成されます。

ファイル・フォルダ構成はこんな感じ。

application.propertiesの作成

次に application.properties に下記を追加します。これも前回と同じです。

spring.datasource.driver-class-name=org.postgresql.Driver
spring.datasource.url=jdbc:postgresql://localhost:5432/postgres
spring.datasource.username=postgres
spring.datasource.password=postgres

MyBatis のデフォルト設定を変えたいときは次のような感じでここに記載します。

mybatis.type-aliases-package=org.yyama
mybatis.type-handlers-package=org.yyama.typehandler
mybatis.configuration.map-underscore-to-camel-case=true
mybatis.configuration.default-fetch-size=100
mybatis.configuration.default-statement-timeout=30

今回はすべてデフォルト設定で行うため、 mybatis.・・・ の記載は不要です。

設定できる Mybatis のプロパティについては公式を参照してください。
www.mybatis.org

パッケージ、フォルダの作成

今回のような小さいアプリケーションでは、すべてのクラスが同じパッケージでも全然 OK なのですが、実業務で応用することを考え、パッケージ分けします。

「org.yyama.controller」・「org.yyama.domain」・「org.yyama.mapper」を作りました。


「org.yyama.controller」はコントローラーの格納場所。

「org.yyama.domain」は テーブルのデータを格納するオブジェクト用のクラス。

「org.yyama.mapper」はテーブルにアクセスするメソッドが記述されたインターフェースを格納します。

インターフェースを実装した具象クラスは MyBatis が自動で作成してくれます。

あと、MyBatis が実行する SQL を記述した XML ファイルの格納場所のフォルダを作成します。「org\yyama\mapper」と同じフォルダ構成を「src/main/resource」配下に作成します。

(パッケージの作成と同じようにドット(.)をつかったらダメですよ。Windows のフォルダなのでバックスラッシュで区切ります。すごくはまります。エラーメッセージはこれです。「org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)」)

こんな感じになりました。(赤枠内のパッケージとフォルダを作成しました。)

クラスとインターフェースの作成

ドメイン、マッパー、コントローラを作成します。

ドメインです。今回は、メンバー変数「name」とその setter、getter だけを持つクラスです。

package org.yyama.domain;

public class Fruit {

	String name;
	
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

}

MyBatis が、このクラスのインスタンスにテーブルのデータを格納してくれるのです。



次にマッパー。インターフェースですが、具象クラスは MyBatis が XML の SQL 情報等を使用し、自動で作成してくれます。
「@Mapper」アノテーションを忘れないでください。

package org.yyama.mapper;

import java.util.List;

import org.apache.ibatis.annotations.Mapper;
import org.yyama.domain.Fruit;

@Mapper
public interface FruitMapper {
	List<Fruit> selectAll();
}


そしてコントローラ。変数「fruitMapper」にMyBatis が自動で生成したマッパーの具象クラスを Spring が DI してくれます。

package org.yyama.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.yyama.domain.Fruit;
import org.yyama.mapper.FruitMapper;

@Controller
public class IndexController {

	@Autowired
	FruitMapper fruitMapper;
	
	@RequestMapping
	public String index(Model model) {
		List<Fruit> list = fruitMapper.selectAll();
		model.addAttribute("fruits", list);
		return "index";
	}
	
}

そして SQL を記述した XML ファイルの作成

resource 配下に作成したフォルダに XML ファイルを作成します。
格納フォルダに注意してください。フォルダは FruitMapper インターフェースのパッケージと同じの階層フォルダ構成としてください。
ファイル名も拡張子以外、 FruitMapper インターフェース名と同じにします。

<?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="org.yyama.mapper.FruitMapper">
    <select id="selectAll" resultType="org.yyama.domain.Fruit">
        SELECT name FROM fruits
    </select>
</mapper>

SQL を直に掛けます。最高です。id とか resultType とか、見た感じで大体イメージ沸きそうですねw。ここでは説明しませんが公式サイトも日本語に翻訳されていますし、ググればいっぱい情報があります。

公式サイト:
http://www.mybatis.org/mybatis-3/ja/

あと Tymeleaf のテンプレート

あとは、resources/templates 配下に Tymeleaf のテンプレートを置きましょう。前回と微妙に異なります。注意してください。

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="utf-8" />
    <title>demo</title>
</head>
<body>
<p th:each="fruit : ${fruits}" th:text="${fruit.name}" />
</body>
</html>

最終的なファイル・フォルダ構成


こんな感じです。


実行する

Spring Boot App で起動して http://localhost:8080 にアクセスするとこのような画面が表示されます。前回と同じですが、MyBatis を使用した大規模プロジェクトでも使える構成になっております。


お疲れ様でした。

Spring 関連の記事は ↓↓↓ にまとめてあります。

Spring 関連記事へのリンク集 - 山崎屋の技術メモ


↓ 俺達、ひたすら勉強しましょう。