この記事ではSpring Boot環境へのMyBatisの導入方法とMyBatisの機能について、紹介して行きたいと思います。
MyBatisとは?

MyBatisはJavaの永続化フレームワークで、DBとJavaオブジェクトを紐づける事ができ、
ORマッパー(Object/RDB Mapper)と呼ばれるます。
MyBatisではXMLやアノテーションを使って設定を行うことができます。
MyBatisは直接SQLを記述する事が可能で、複雑なSQLやパフォーマンスチューニングが必要なケースで威力を発揮します。
以前はiBATISというApacheプロジェクトで開発されていましたが、2010年からMyBatisというプロジェクト名に変更され開発が続いています。
公式でSpring Boot環境で利用するためのstarterライブラリが提供されているため、非常に簡単に導入することが可能です。
公式サイト
https://mybatis.org/
環境
- Spring Boot: 2.5.4
- Java 11
- gradle
- DB: H2(インメモリDB)
MyBatisの導入
build.gradleにMyBatisのスターターライブラリとDBとして使用するH2のライブラリを追加します。
dependencies {
implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:2.2.0'
runtimeOnly 'com.h2database:h2:1.4.200'
testImplementation 'org.springframework.boot:spring-boot-starter-test:2.5.4'
}
次にSpring Bootの設定ファイル(application.yml)にh2への接続設定を行います。
spring:
datasource:
url: jdbc:h2:mem:testdb
driverClassName: org.h2.Driver
username: sa
password:
上記の設定ではtestdbという名前のインメモリDBを使用するようにしています。
ここまででMyBatisを利用する準備が整いました。
データベーステーブルの準備
この記事ではタスクを管理するテーブルを題材に説明を進めます。
よくあるTODO管理を思い浮かべるとわかりやすいと思います。

タスクテーブル(task)
タスクを管理するテーブル
カラム名 | 名称 | タイプ | 属性 |
id | ID | int | KEY NOT NULL 自動採番 |
task_desc | タスク名 | varchar(1000) | NOT NULL |
done | 完了 | boolean | NOT NULL デフォルト値: false |
created_at | 作成日時 | timestamp | NOT NULL |
updated_at | 更新日時 | timestamp |
タスクタグテーブル(task_tag)
タスクに紐づけるタグを管理するテーブル。
1件のタスクに対して複数件紐づけることができます。
カラム名 | 名称 | タイプ | 属性 |
id | ID | int | KEY NOT NULL 自動採番 |
task_id | タスクID | int | NOT NULL FK(task:id) |
tag_name | タグ名 | varchar(100) | NOT NULL |
order_seq | 表示順 | int | NOT NULL |
created_at | 作成日時 | timestamp | NOT NULL |
updated_at | 更新日時 | timestamp |
データの初期化
Spring BootにはDBを初期化する機能があり、クラスパス上(src/main/resources直下)に決められたsqlファイルを配置するだけでアプリケーションの実行時に自動的に初期化を実行してくれます。
- schema.sql: DDL(テーブル作成文など)を記述
- data.sql: insert文などのデータ操作文を記述
-- タスク
create table task
(
id int not null auto_increment,
task_desc varchar(1000) not null,
done boolean not null default false,
created_at timestamp not null,
updated_at timestamp,
primary key (id)
);
-- タスクタグ
create table task_tag
(
id int not null auto_increment,
task_id int not null,
tag_name varchar(100) not null,
order_seq int not null,
created_at timestamp not null,
updated_at timestamp,
primary key (id),
foreign key (task_id) references task (id)
);
insert into task values (1, '買い物に行く', false, '2020-12-20 10:20:10');
insert into task values (2, 'スケジュールを作る', false, '2021-03-01 18:05:42');
insert into task values (3, '会議を招集する', false, '2021-05-23 13:05:42');
insert into task_tag values(1, 1, 'プライベート', 1, '2020-12-20 10:20:10');
insert into task_tag values(2, 1, '外出', 2, '2020-12-20 10:20:10');
insert into task_tag values(3, 2, '仕事', 1, '2021-03-01 18:05:42');
insert into task_tag values(4, 2, '急ぎ', 2, '2021-03-01 18:05:42');
insert into task_tag values(5, 3, '仕事', 1, '2021-05-23 13:05:42');
insert into task_tag values(6, 3, '定例', 2, '2021-05-23 13:05:42');
MyBatisを使ったDBアクセスの実装
MyBatisを使ってDBへアクセスするために必要なもの
エンティティクラス | テーブル・ビューと値をやり取りするためのクラス |
マッパーインターフェース | DBテーブルへの動作を定義するためのインターフェース |
マッパーXML | 実行するSQLやDBテーブルとエンティティクラスへのマッピングなどを記述するXMLファイル。 XMLを使用せずにマッパーインターフェースにアノテーションで定義することも可能。 |
エンティティクラスの実装
タスクテーブル、テスクタブテーブルをマッピングするためのエンティティクラスを実装します。
エンティティクラスは特定のインターフェースの実装やアノテーションの付与などは必要ありません。
値を保持する為のフィールドにはgetter, setterを定義する必要があります。
この記事ではgetter, setterの自動生成のためにLombokというライブラリを利用しています。(※1)
package com.example.springbootmybatis.entity;
import lombok.Data;
import java.time.LocalDateTime;
@Data // ※1
public class Task {
private int id;
private String taskDesc;
private boolean done;
private LocalDateTime createdAt;
private LocalDateTime updatedAt;
}
package com.example.springbootmybatis.entity;
import lombok.Data;
import java.time.LocalDateTime;
@Data
public class TaskTag {
private int id;
private int taskId;
private String tagName;
private int orderSeq;
private LocalDateTime createdAt;
private LocalDateTime updatedAt;
}
マッパーインターフェースの実装
DBテーブルへの動作を定義するためにマッパーインターフェースを実装します。
まずはタスクテーブルを操作するためのTaskMapperを作成し、全てのタスクを取得するfindAllメソッドを定義します。
package com.example.springbootmybatis.mapper;
import com.example.springbootmybatis.entity.Task;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface TaskMapper {
public List<Task> findAll();
}
インターフェースに@Mapperアノテーションを付与することで自動的にSpringのBeanとして登録されます。
マッパーXMLの実装
先ほど実装したTaskMapperの対となるマッパーXMLを実装します。
マッパーXMLはsrc/main/resources以下に配置し、マッパーインターフェースのパッケージ配置と同じ配置にインターフェース名と同名になるように配置します。
TaskMapperはcom.example.springbootmybatis.mapperパッケージに配置されていますので、マッパーXMLはsrc/main/resources/com/example/springbootmybatis/mapper/TaskMapper.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.springbootmybatis.mapper.TaskMapper">
<resultMap id="Base_Result_Map" type="com.example.springbootmybatis.entity.Task">
<id column="id" property="id" jdbcType="INTEGER"/>
<result column="task_desc" property="taskDesc" jdbcType="VARCHAR"/>
<result column="done" property="done" jdbcType="BOOLEAN"/>
<result column="created_at" property="createdAt" jdbcType="TIMESTAMP"/>
<result column="updated_at" property="updatedAt" jdbcType="TIMESTAMP"/>
</resultMap>
<select id="selectAll" resultMap="Base_Result_Map">
select
id, task_desc, done, created_at, updated_at
from task
order by id
</select>
</mapper>
resultMapの定義
resultMapタグを定義し、エンティティクラスとテーブルカラムの紐づけを行います。
id属性にこのresultMapを特定するためのIDを指定し、type属性に紐づけるエンティティクラスを指定します。
次にresultMapタグの子要素にテーブルカラムの定義を行います。
キーカラムにはidタグを使い、キー以外のカラムにはresultタグを使用し、column属性にテーブルカラム名を指定し、property属性にエンティティクラスのフィールド名をしています。
jdbcType属性にはテーブルカラムの型を指定します。jdbcType属性の一覧はこちら。
selectの定義
selectタグを定義し、 TaskMapperのselectAllメソッドと紐づけるSQLを定義します。
id属性には紐づけるメソッド名を指定する必要がありますので、ここではselectAllを設定します。
resultMap属性には結果として返却する定義情報を指定する必要があり、先ほど定義したresultMapのidを指定します。最後にselectタグのテキストには実際に実行するSQLを記述します。
TaskMapperの実行
ここまででMyBatisを実行するための準備が整いましたので、TaskMapperを実行して全てのタスクを取得してみましょう。
package com.example.springbootmybatis.service;
import com.example.springbootmybatis.entity.Task;
import com.example.springbootmybatis.mapper.TaskMapper;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class TaskServiceImpl implements TaskService {
private final TaskMapper taskMapper;
// コンストラクタインジェクション
public TaskServiceImpl(TaskMapper taskMapper) {
this.taskMapper = taskMapper;
}
@Override
public List<Task> findAll() {
return taskMapper.findAll();
}
}
TaskMapperはSpringのBeanとして登録されていますので、他のBeanにDIする事が可能です。上のサンプルではコンストラクターインジェクションでTaskServiceImplにインスタンスを注入しています。
まとめ
この記事ではSpring Boot環境でMyBatisを使えるようにする設定を説明しました。
次回はMyBatisの機能を中心に説明していきたいと思います。
最後までお読みいただき、ありがとうございました。
コメント