Spring Bootの案件にアサインされて、いきなり「DBアクセスはMyBatisで」と言われて固まった経験はありませんか。私はあります。
JPAしか触った経験がなかったので、MapperだのresultMapだのXMLだの、最初は正直「なんでSQLを手で書くの?」状態でした。
ただ、業務系の現場で数年MyBatisを使ってみて分かったのは、「SQLを自分で書ける」のは弱点ではなく武器だという事実です。
さらにMyBatis Generatorを組み合わせれば、退屈なCRUDコードは全部自動生成できます。手で書くのは複雑なSQLだけ。
この分業が決まると開発がかなり楽になります。
この記事では、MyBatisの基本構成(Mapper・XML・設定の3ファイル)と、MyBatis Generatorの導入から実行までを5ステップで解説します。
初めてMyBatis案件に入るJavaエンジニアが、最初の1週間でつまずくポイントを一通り潰せる内容にしました。
MyBatisとは?SQLを自分で書けるO/Rマッパー
MyBatisとは、SQLを開発者自身が書き、その実行結果とJavaオブジェクトの変換(マッピング)だけをフレームワークに任せるO/Rマッパーです。
SQLはXMLファイルまたはアノテーションに記述し、Javaのメソッドに紐づけます。
@Mapper"] Entity["Entityクラス
JavaBeans"] end subgraph MyBatis["MyBatis"] XML["マッピングXML
SQL定義 + resultMap"] Config["設定
application.yml"] end subgraph DB["データベース"] Table["テーブル"] end Mapper --> |"メソッド呼び出し"| XML XML --> |"SQL実行"| Table Table --> |"結果セット"| XML XML --> |"自動マッピング"| Entity Config --> |"接続設定"| XML
JPAのようにSQLを自動生成するタイプとは思想が真逆で、「SQLは人間が書いたほうが速くて正確」という割り切りが特徴です。
国内ではSIerや業務系システムでの採用が多く、Spring Bootと組み合わせる構成が定番です。
テーブル結合が複雑な帳票系・検索系のシステムだと、JPAで頑張るよりMyBatisで生SQLを書くほうが圧倒的に見通しがよくなります。
私の現場でも、5テーブル結合の検索SQLをJPQLで書いていた頃と比べて、レビュー時間が体感で半分になりました。
O/Rマッパーとは?MyBatisの立ち位置
O/Rマッパーとは、リレーショナルデータベースの行データとJavaオブジェクトを相互変換する仕組みです。
素のJDBCだとResultSetから1カラムずつ値を取り出す退屈なコードが必要ですが、O/Rマッパーがあれば結果を自動でオブジェクトに詰めてくれます。
MyBatisはO/Rマッパーの中でも「SQLは書く、詰め替えは任せる」という半自動タイプに分類されます。
JPA(Hibernate)との違いと使い分け
結論、SQLを細かく制御したいならMyBatis、単純なCRUD中心ならJPAが向いています。両者の違いを表にまとめました。
| 観点 | MyBatis | JPA(Hibernate) |
|---|---|---|
| SQL | 自分で書く | 基本は自動生成 |
| 複雑な結合・チューニング | 得意 | 苦手になりがち |
| 単純なCRUDの記述量 | 多い(Generatorで解決) | 少ない |
| 学習コスト | SQLが書ければ低い | エンティティ管理の理解が必要 |
| 国内の採用傾向 | 業務系・SIerに多い | Web系・海外に多い |
「単純なCRUDの記述量が多い」というMyBatis唯一の弱点を埋めるのが、後半で解説するMyBatis Generatorです。
MyBatisの基本!最小構成は3つのファイル
MyBatisを動かす最小構成は、Mapperインターフェース・マッピングXML・接続設定の3ファイルです。
Spring Boot環境ならmybatis-spring-boot-starterを依存に追加するだけで、面倒な初期化コードは不要になります。
まずは3ファイルの役割を順に見ていきましょう。
Mapperインターフェースの役割
Mapperインターフェースは「JavaコードからSQLを呼び出す窓口」です。実装クラスは書きません。
メソッドを定義しておくと、MyBatisが実行時に自動で実装を生成してくれます。
@Mapper
public interface UserMapper {
// XMLに書いたSQLのid="selectById"と紐づく
User selectById(Long id);
// 簡単なSQLならアノテーションでも書ける
@Select("SELECT COUNT(*) FROM users")
long countAll();
}
アノテーションとXMLは併用できます。1〜2行のSQLはアノテーション、長いSQLはXML、と使い分けるのが現場の定番です。
マッピングXMLの書き方
マッピングXMLには、Mapperのメソッド名をidにしてSQLを書きます。
namespaceにMapperインターフェースの完全修飾名を指定するのがポイントです。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.mapper.UserMapper">
<select id="selectById" resultType="com.example.entity.User">
SELECT id, name, email
FROM users
WHERE id = #{id}
</select>
</mapper>
パラメータは#{id}のように書きます。内部ではプレースホルダに変換されるため、SQLインジェクション対策も兼ねています。
文字列連結になる${}は原則使わない、と覚えておけばOKです。
Spring Bootとの連携設定
Spring Bootなら、依存追加とapplication.ymlへの数行の設定だけで動きます。
spring:
datasource:
url: jdbc:postgresql://localhost:5432/sampledb
username: app
password: secret
mybatis:
mapper-locations: classpath:mapper/*.xml
configuration:
map-underscore-to-camel-case: true
map-underscore-to-camel-caseを有効にすると、DBのuser_nameをJavaのuserNameへ自動変換してくれます。地味ですが必須級の設定です。
MyBatis Generatorとは?何を自動生成できる?
MyBatis Generatorとは、データベースのテーブル定義を読み取り、MyBatisに必要なファイル一式を自動生成する公式ツールです。テーブルが30個あるプロジェクトで、Entityを30個・Mapperを30個・XMLを30個手書きするのは苦行でしかありません。Generatorならコマンド1発、数秒で終わります。
私が初めて使ったときは、90ファイル分の作業が5分で終わって軽く感動しました。
タイポによるバグも根絶できるので、「単純作業は機械に任せる」効果は想像以上に大きいです。
自動生成される3種類のファイル
Generatorが生成するのは次の3種類です。テーブル1つにつき1セット作られます。
- Entityクラス:テーブルのカラムに対応したJavaBeans(例:
User.java) - Mapperインターフェース:insert/update/delete/selectの基本メソッド一式
- マッピングXML:基本メソッドに対応するSQLと
resultMap定義
つまり、前の章で手書きした3ファイルのうち、CRUDに関する部分は全部Generatorが肩代わりしてくれる構図です。
Exampleクラスとは?条件指定の仕組み
Exampleクラスとは、WHERE句をJavaコードで組み立てるための条件ビルダーです。
設定で生成をONにすると、テーブルごとにUserExampleのようなクラスが追加されます。
UserExample example = new UserExample();
example.createCriteria()
.andNameLike("%佐藤%")
.andEmailIsNotNull();
List<User> users = userMapper.selectByExample(example);
SQLを書かずに動的な検索条件を作れるのが利点です。ただし結合を含む検索には使えないので、あくまで単一テーブルの絞り込み用と割り切りましょう。
MyBatis Generatorの使い方5ステップ
導入から実行までの流れは、Mavenプラグイン追加→設定ファイル作成→実行→生成物確認→CRUD実装の5ステップです。
ここではMaven + PostgreSQLの構成を例にします。Gradleでも流れは同じで、プラグインの書き方が変わるだけです。
ステップ1: Mavenプラグインの追加
pom.xmlにGeneratorのプラグインを追加します。JDBCドライバはプラグインの依存として指定するのがポイントです。
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.4.2</version>
<dependencies>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.7.3</version>
</dependency>
</dependencies>
</plugin>
ステップ2: generatorConfig.xmlの作成
プロジェクト直下にgeneratorConfig.xmlを作り、DB接続情報・出力先パッケージ・対象テーブルを指定します。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration PUBLIC
"-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"https://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<context id="default" targetRuntime="MyBatis3">
<jdbcConnection driverClass="org.postgresql.Driver"
connectionURL="jdbc:postgresql://localhost:5432/sampledb"
userId="app" password="secret" />
<javaModelGenerator targetPackage="com.example.entity"
targetProject="src/main/java" />
<sqlMapGenerator targetPackage="mapper"
targetProject="src/main/resources" />
<javaClientGenerator type="XMLMAPPER"
targetPackage="com.example.mapper"
targetProject="src/main/java" />
<table tableName="users" />
<table tableName="orders" />
</context>
</generatorConfiguration>
targetRuntimeをMyBatis3にするとExampleクラスあり、MyBatis3Simpleにするとなしで生成されます。
迷ったら、まずはシンプルな後者から始めるのがおすすめです。
ステップ3: 生成コマンドの実行と確認
準備ができたら、次のコマンドを実行するだけです。
mvn mybatis-generator:generate
成功すると、指定したパッケージにEntity・Mapper・XMLが出力されます。
BUILD SUCCESSが出たら、まず生成されたXMLを開いてSQLの内容を眺めてみてください。
MyBatisの書き方のお手本として、そのまま教材になります。
ステップ4〜5: 生成コードでCRUDを書く
生成されたMapperをServiceクラスに注入すれば、SQLを1行も書かずにCRUDが完成します。
@Service
@RequiredArgsConstructor
public class UserService {
private final UserMapper userMapper;
public User find(Long id) {
return userMapper.selectByPrimaryKey(id);
}
public void register(User user) {
userMapper.insertSelective(user);
}
}
insertSelectiveはnullでないフィールドだけをINSERT文に含めるメソッドで、デフォルト値をDB側に任せたい場面で便利です。
ここまで動けば導入は完了。あとは複雑な検索だけ自作のXMLを足していく運用になります。
MyBatis Generator利用時の注意点3つ
Generatorは便利ですが、運用ルールを決めずに使うと事故ります。
注意点は「再生成による上書き」「複雑なSQLへの過信」「生成コードの管理方針」の3つです。
特に1つ目は、私も過去に半日分の修正を吹き飛ばした苦い経験があります。順に対策を見ていきましょう。
再生成で手動修正が消える問題への対策
テーブル定義の変更後に再生成すると、生成ファイルへの手動修正は原則すべて上書きされます。
対策はシンプルで、「生成ファイルは一切編集しない」をチームルールにすることです。
独自SQLはUserCustomMapperのような別ファイルに分離し、生成物と手書きをパッケージ単位で分けておけば、いつでも安心して再生成できます。
複雑なSQLは手書きと使い分ける
Generatorが面倒を見てくれるのは単一テーブルのCRUDまでです。結合・集計・サブクエリを含むSQLは、素直に自分でXMLに書きましょう。
Exampleクラスを無理にこね回して複雑な条件を作ると、SQLの全体像がコードに埋もれて逆に読みにくくなります。
「単純作業はGenerator、腕の見せどころは手書き」の線引きが快適さの鍵です。
なお生成コードはGit管理に含め、再生成時の差分をレビューで確認できるようにしておくと安全です。
手を動かしながら体系的に理解を深めたい方には「完全攻略!MyBatisプログラミング入門」をAmazonで見るもおすすめです(楽天市場 / Yahoo!ショッピングでも購入可能)。
ExampleクラスやGeneratorの実装パターンをより深く学べます。
MyBatisの基本に関するよくある質問(FAQ)
MyBatisを始めたばかりの頃に私自身が検索した疑問を中心に、Q&A形式でまとめました。
Q1. MyBatisとは何ですか?
SQLを開発者が書き、実行結果とJavaオブジェクトのマッピングを自動化するO/Rマッパーです。
XMLまたはアノテーションでSQLをメソッドに紐づけます。
Q2. MyBatisの読み方は?
「マイバティス」と読みます。前身のフレームワーク「iBATIS(アイバティス)」が2010年に改名して生まれました。
Q3. MyBatisとJPAはどちらを選ぶべき?
複雑なSQLやチューニングが必要ならMyBatis、単純なCRUD中心の小規模アプリならJPAが向いています。
国内の業務系案件ではMyBatis採用が多数派です。
Q4. MyBatis Generatorは何を生成しますか?
テーブル定義をもとに、Entityクラス・Mapperインターフェース・マッピングXMLの3種類を生成します。
設定により条件ビルダーのExampleクラスも追加できます。
Q5. 生成されたコードは編集していいですか?
いいえ、編集しないのが原則です。再生成で上書きされるため、独自の処理は別ファイルに分離してください。
Q6. GradleでもMyBatis Generatorは使えますか?
はい、使えます。
コミュニティ製のGradleプラグインを利用するか、Generatorを単体のJavaプログラムとして実行する方法があります。
まとめ: MyBatisはSQL好きのためのO/Rマッパー
MyBatisの基本とGeneratorの使い方を、要点だけ振り返ります。
- MyBatisはSQLを自分で書くO/Rマッパー。複雑なSQLが多い案件で強い
- 最小構成はMapperインターフェース・マッピングXML・接続設定の3ファイル
- MyBatis GeneratorはCRUD一式を自動生成し、単純作業を数秒に短縮する
- 導入はMavenプラグイン追加→generatorConfig.xml→
mvn mybatis-generator:generateの流れ - 生成ファイルは編集禁止。独自SQLは別ファイルに分離して再生成に備える
正直、SQLを書きたくない人にMyBatisは向きません。
でも「ORMの自動生成SQLにモヤモヤした経験がある」「実行されるSQLを自分の目で確認したい」タイプなら、間違いなくハマります。
まずは検証用のプロジェクトでGeneratorを1回動かしてみてください。90ファイルが数秒で生まれる体験をすると、もう手書きには戻れなくなりますよ(笑)。



