Spring MVC + MyBatis3でDBアクセス環境構築

Spring
Spring

こちら↓の記事に引き続き、環境構築シリーズです。今度はSpring MVCをデータベースとつなげます。

Spring MVC + Thymeleaf + Gradle で開発環境構築
この記事書くだけでもかな~りハマりました。やっぱり環境構築って嫌い。 というわけで、Spring MVC (Bootじゃないよ) + Thymeleaf + Gradle という環境で環境構築をしたので書き残しておきます。 IDEに...

DBアクセスのフレームワークにはMyBatisを使用します。

MyBatis(マイバティス)とは?

Javaの永続化フレームワーク(データベース用フレームワーク)の一種で、XMLまたはアノテーションを用いてオブジェクトとSQLをマッピングするO/Rマッパーです。DB用フレームワークの中では有名なほうであり、ネット上にも参考になるサイトが多くあります。Springとの親和性も高いので、Spring(Boot含む)でアプリを作るときの筆頭候補になるのではないかなと思います。

この記事では、Spring MVC + MyBatis3 という構成で、DBに保持されている値をブラウザに出すところまで作ってみようと思います。MyBatisの詳細な使い方についてはまた別の記事で書きたいと思います。この記事はとにかく動くこと優先で。

環境情報
  • Windows 10 Home
  • PostgreSQL 12
前提条件
  1. Spring MVCを使用してローカル環境にてブラウザからアクセスが可能となっていることを前提とします。この条件を満たせていない場合は、こちらの記事などを活用してSpring MVCの環境構築を行ってください。
  2. データベースにテーブルが作成されていて、すでにデータが入っているという前提で進めます。今回は例として下記のテーブルを作成しています。
CREATE TABLE task
(
    task_id character varying(20) COLLATE pg_catalog."default" NOT NULL,
    title character varying(100) COLLATE pg_catalog."default" NOT NULL,
    CONSTRAINT task_pkey PRIMARY KEY (task_id)
)

中のデータはこんな感じです。

SELECT * FROM task;
 task_id | title
---------+-------
 123     | 仕事
 456     | 勉強

では、頑張って環境構築していきましょう!

依存関係の定義

build.gradle

まずは、MyBatisを動かすために必要な依存ライブラリを貰ってきましょう。

apply plugin: 'java'
apply plugin: 'war'
apply plugin: 'eclipse-wtp'
apply plugin: 'eclipse'

sourceCompatibility = 1.8
targetCompatibility = 1.8

repositories {
    jcenter()
}

dependencies {
    // Spring MVC
    compile group: 'org.springframework', name: 'spring-webmvc', version: '5.3.3'
    compile group: 'org.thymeleaf', name: 'thymeleaf-spring4', version: '3.0.12.RELEASE'

    // Spring JDBC
    compile group: 'org.springframework', name: 'spring-jdbc', version: '5.3.3'

    // MyBatis
    compile group: 'org.mybatis', name: 'mybatis-spring', version: '2.0.6'
    compile group: 'org.mybatis', name: 'mybatis', version: '3.5.6'

    // PostreSQL Driver
    compile group: 'org.postgresql', name: 'postgresql', version: '42.2.18'

}

ローカルでMyBatisを動かすには「mybatis-spring」「mybatis」「spring-jdbc」の3つのライブラリを依存関係に追加します。「mybatis-spring」のみを追加してもデプロイ時にこけるので、3つとも追加するようにしてください。もしかしたらもっとスマートな書き方があるかもしれないです。。
ちなみにSpringBootだと「mybatis-spring-boot-starter」というライブラリがあって、これ1つだけ追加すればMyBatisが使えるようになるみたいです。(Compile DependenciesとProvided Dependenciesの違いだから、もしかしたらBootじゃなくても使えたりする?)

あとはデータベースに接続するためのドライバーももらっておきます。今回はPostgreSQLを使用するので、「postgresql」を依存関係に追加しました。

build.gradleを編集した後は、「Gradle プロジェクトのリフレッシュ」を忘れずに実行してください。

SpringのBean定義&MyBatisの設定

MyBatisを動作させるために必要なクラスをSpringのBeanとして定義していきます。また、MyBatis固有の設定も行っていきます。

applicationContext.xml

SpringのBean定義ファイルです。下記のソースを追加します。

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:mybatis="http://mybatis.org/schema/mybatis-spring"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-4.3.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd
        http://mybatis.org/schema/mybatis-spring
        http://mybatis.org/schema/mybatis-spring.xsd">

    <!-- 一部省略 -->

    <!-- データソースの設定 各自の環境の情報に合わせて設定してください -->
    <bean id="dataSource"
        class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="org.postgresql.Driver" />
        <property name="url" value="jdbc:postgresql://localhost:5432/postgres" />
        <property name="schema" value="public" />
        <property name="username" value="postgres" />
        <property name="password" value="postgres" />
    </bean>

    <!-- MyBatisを動作させるのに必要なsqlSessionFactoryを定義 -->
    <bean id="sqlSessionFactory"
        class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="configLocation"
            value="/WEB-INF/mybatis/mybatis-config.xml" />
    </bean>

    <!-- MyBatisのマッパーインターフェースが格納されている基底パッケージを指定 -->
    <!-- このパッケージ配下にあるインターフェースに対して実装クラスを自動生成してくれる -->
    <!-- それらはSpringのBeanとしてControllerやServiceにDIして使用可能 -->
    <mybatis:scan base-package="sample.mybatis.domain.mapper" />

</beans>

データソースに関しては、すでに別で定義されている場合は追加する必要はありません。
sqlSessionFactoryは、MyBatisでのDBアクセスには必須のクラスです。必ず定義してください。プロパティとして指定するのは、データソースのBeanと、MyBatisの設定ファイルのありかです。

mybatis:scanタグでは、MyBatisのマッパーインターフェースの基底パッケージを指定します。指定されたパッケージの中をスキャンしてマッパーインターフェースを抽出し、それに対して実装クラスを自動生成することでMyBatisを介してのDBアクセスができるようになります。また、それらはSpringのBeanとして扱われるので、ControllerクラスやServiceクラスにDIして使用することができます。Springとしてのcontext:component-scanのMyBatis版と考えるといいと思います。

ちなみに

パッケージスキャンではなく、個別でマッパーインターフェースをBean登録する場合はこんな感じです。

<bean id="taskMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
    <property name="mapperInterface" value="sample.mybatis.domain.mapper.TaskMapper" />
    <property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>

マッパーが数十個~百個以上となってくると、個別でBean定義するのはつらくなってくると思います。最初からスキャンでBean定義することを念頭に置いてパッケージを構成してください。

mybatis:scanタグを使用する際は、最初のbeansタグのschemaLocationに「http://mybatis.org/schema/mybatis-spring」と「http://mybatis.org/schema/mybatis-spring.xsd」が追加されており、「xmlns:mybatis=”http://mybatis.org/schema/mybatis-spring”」の設定がされていることを確認してください。忘れられがちですが、これを追加しておかないとタグとして認識されずうまく動作しません。

mybatis-config.xml

MyBatisの設定ファイルです。設定できる項目はいろいろありますが、今回はエイリアスの登録だけ実施します。

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
    PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <typeAliases>
        <package name="sample.mybatis.domain.mapper" />
        <package name="sample.mybatis.domain.entity" />
    </typeAliases>
</configuration>

エイリアス登録とは、MyBatisのXMLでJavaのクラス名を指定する場合に
sample.mybatis.domain.entity.Task」⇒「Task
という風に、パッケージ名を省略しても認識するように、別名(エイリアス)を登録することです。
エンティティのパッケージとマッパーインターフェースのパッケージを登録しておくことをオススメします。

MyBatisでSELECTを実行

ここまでで、MyBatisで開発をする準備が整いました。ここからは、実際にソースを書いて、ブラウザからDBアクセスしていきます。

Entityクラス (Task.java)

package sample.mybatis.domain.entity;

public class Task {

    private String taskId;
    private String title;

    // Setter | Getterは省略
}

Mapperインターフェース (TaskMapper.java)

package sample.mybatis.domain.mapper;

import sample.mybatis.domain.entity.Task;

public interface TaskMapper {

    public Task selectById(String taskId);

    // 今回は使わないけど定義だけ
    public void insert(Task entity);

}

DBアクセスの際のインターフェースを定義します。アノテーションを使用することで、このインターフェース内でSQLを定義して実行させることも可能ですが、今回はXMLファイルを作成してそこにSQLを定義する方法を採用します。

SQL定義XML (TaskMapper.xml)

src/main/resourcesディレクトリ内に、対応するマッパーインターフェースと同じ階層、同じ名前で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="sample.mybatis.domain.mapper.TaskMapper">

    <!-- テーブルのカラムとエンティティの属性のマッピングを定義 -->
    <resultMap id="resultMapTask" type="Task">
        <id property="taskId" column="task_id" />
        <result property="title" column="title" />
    </resultMap>

    <select id="selectById" parameterType="string" resultMap="resultMapTask">
        SELECT * FROM task WHERE task_id = #{taskId}
    </select>

    <!-- 今回は使わないけど定義だけ -->
    <insert id="insert" parameterType="Task">
        INSERT INTO task (task_id, title) VALUES(#{taskId}, #{title})
    </insert>
</mapper>

流すSQLの種類によって使用するタグが変わります。SELECT文の場合はselectタグ、INSERT文の場合はinsertタグ、といった具合です。idはマッパーインターフェースのメソッド名と対応させます。parameterTypeには、引数として受け取る値の型を指定します。resultMapでは、取得した結果をオブジェクトに変換するマッパーを指定します。他にも設定できる項目は多くあります。詳細はMyBatisの公式ガイドを参照ください。

ちなみに

selectByIdのparameterTypeが「”string”」と小文字で表記されていますが、これはMyBatisが汎用的なJavaクラスに対してエイリアスを設定しているためです。他にも多くのクラスがエイリアス設定されており、プリミティブ型とそのラッパークラスの区別もつけられるようになっています。詳細はこちらを参照ください。

Controller&HTML

すべてのファイルの準備ができたら、いよいよMyBatisを使ってDBアクセスをしてみましょう!

まずはコントローラーから。

@Controller
public class TaskController {

    private TaskMapper taskMapper;

    public TaskController(TaskMapper taskMapper) {
        // Beanとして定義されているのでコントローラー呼び出し時に自動で代入される
        this.taskMapper = taskMapper;
    }

    @GetMapping
    public String index() {
        return "index";
    }

    // idをパスに指定してデータを取得
    @GetMapping("/{id}")
    public String create(@PathVariable("id") String id, Model model) {
        // DBアクセスインターフェースを利用
        Task task = taskMapper.selectById(id);
        model.addAttribute("title", task.getTitle());
        return "index";
    }
}

続いてHTML、Thymeleafを使用しています。

<!DOCTYPE html>

<html xmlns:th="http://www.thymeleaf.org">
    <head>
        <title>タスク</title>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    </head>
    <body>
        <h1 th:text="${title}"></h1>
    </body>
</html>

DBアクセス実行

ここまで準備が整ったら、サーバにデプロイをしてアクセスしてみます。
ブラウザのアドレスバーに「http://localhost:8080/{contextPath}/123」と入力してアクセスします。

タスクのタイトルが表示されました!
idを456に変更してみると、、、

こちらも表示されました!


おわりに

前回の記事と合わせて、Spring MVCでアプリケーションを作る環境がざっと整いました!
今後はSpringでのコーディングの方法だとか、Javaのイケてるコーディングの方法だったりとかを投稿していこうかと思います。

コメント

タイトルとURLをコピーしました