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の基本構成とJPAとの使い分け
- Mapperインターフェース・マッピングXMLの書き方
- MyBatis Generatorの導入〜実行の5ステップ
- 再生成でコードが消える事故を防ぐ運用ルール
PARTS LIST /目次
MyBatisとは?SQLを自分で書けるO/Rマッパー
MyBatisとは、SQLを開発者自身が書き、その実行結果とJavaオブジェクトの変換(マッピング)だけをフレームワークに任せるO/Rマッパーです。
SQLはXMLファイルまたはアノテーションに記述し、Javaのメソッドに紐づけます。
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が向いています。両者の違いを表にまとめました。
「単純なCRUDの記述量が多い」というMyBatisの代表的な弱点を埋めるのが、後半で解説するMyBatis Generatorです。
MyBatisの基本!最小構成は3つのファイル
MyBatisを動かす最小構成は、Mapperインターフェース・マッピングXML・接続設定の3ファイルです。
Spring Boot環境ならmybatis-spring-boot-starterを依存に追加するだけで、面倒な初期化コードは不要になります。
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です。
foreachでIN句に複数の値を渡す
条件に渡す値の数が実行時に変わる場合は、動的SQLの<foreach>でIN句を組み立てます。複数のIDをまとめて検索する場面で使います。
まず、MapperインターフェースでListを受け取るメソッドを用意します。
// 複数のIDをListで受け取る。@Paramの名前がXMLのcollectionと対応する
List<User> selectByIds(@Param("ids") List<Long> ids);
XMLでは、foreachがListの要素を1つずつ取り出してIN句の括弧の中を作ります。
<select id="selectByIds" resultType="com.example.entity.User">
SELECT id, name, email
FROM users
WHERE id IN
<foreach collection="ids" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</select>
idsに3件のIDを渡すと、SQLはWHERE id IN (?, ?, ?)の形で実行され、値は#{id}のプレースホルダとして渡されます。値を文字列連結しないので、前述のSQLインジェクション対策はそのまま効きます。
foreachの主な属性は次の通りです。
collection:ループ対象のコレクション。@Paramで付けた名前を指定するitem:ループの中で現在の要素を受け取る変数名index:ループの回数。Mapを渡した場合はキーになるopen・close:ループ全体の前後に付ける文字列(ここでは括弧)separator:要素と要素の間に入れる文字列(ここではカンマ)
属性の仕様はMyBatis公式ドキュメントの動的SQLで確認できます。
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コードで組み立てるための条件ビルダーです。
targetRuntimeがMyBatis3のとき、テーブルごとにUserExampleのようなクラスが標準で追加されます(MyBatis3Simpleでは生成されません)。
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の作成
src/main/resources/generatorConfig.xmlを作り(Mavenプラグインが標準で探す場所です)、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" domainObjectName="User" />
<table tableName="orders" />
</context>
</generatorConfiguration>
targetRuntimeをMyBatis3にするとExampleクラスあり、MyBatis3Simpleにするとなしで生成されます。
テーブル名usersのままだと生成クラス名はUsersになるため、domainObjectName="User"でUserに指定しています。
Exampleクラスが不要ならMyBatis3Simpleで足りますが、insertSelectiveやselectByExampleなどのメソッドも生成されません。この記事ではどちらも使うため、MyBatis3のまま進めます。
ステップ3〜4: 生成コマンドの実行と生成物の確認
準備ができたら、次のコマンドを実行するだけです。
mvn mybatis-generator:generate
成功すると、指定したパッケージにEntity・Mapper・XMLが出力されます。
BUILD SUCCESSが出たら、まず生成されたXMLを開いてSQLの内容を眺めてみてください。
MyBatisの書き方のお手本として、そのまま教材になります。
ステップ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側に任せたい場面で便利です。
注意点として、Generatorが生成したMapperインターフェースには@Mapperが付きません。このままではSpring Bootがスキャンせず、注入時にBeanが見つからないエラーになります。アプリケーションクラスに@MapperScan("com.example.mapper")を付けるか、generatorConfig.xmlにMapperAnnotationPluginを設定して@Mapperを付けて生成してください。
ここまで動けば導入は完了。あとは複雑な検索だけ自作のXMLを足していく運用になります。
MyBatis Generator利用時の注意点3つ
Generatorは便利ですが、運用ルールを決めずに使うと事故ります。
注意点は「再生成による上書き」「複雑なSQLへの過信」「生成コードの管理方針」の3つです。
特に1つ目は、私も過去に半日分の修正を吹き飛ばした苦い経験があります。順に対策を見ていきましょう。
再生成で手動修正が消える問題への対策
テーブル定義の変更後に再生成すると、生成された部分への手動修正は失われます。Mavenプラグインの既定(overwriteがfalse)では、既存のJavaファイルは上書きされずUser.java.1のような別名で出力されます。XMLは生成済みのSQLが入れ替わり、手書きで足した要素は残ります。overwriteをtrueにするとJavaファイルも上書きされます。
対策はシンプルで、「生成ファイルは一切編集しない」をチームルールにすることです。
独自SQLはUserCustomMapperのような別ファイルに分離し、生成物と手書きをパッケージ単位で分けておけば、いつでも安心して再生成できます。
User.javaUserMapper.javaUserMapper.xmlテーブル1つにつき3ファイルを生成。テーブル定義の変更後に再生成すると、生成された部分への手動修正は失われるNG:直接編集しないUserCustomMapper独自SQLは別ファイルに分ける。再生成の影響を受けずに残るOK:いつでも再生成できるoverwriteがfalse)では、既存のJavaファイルはUser.java.1のような別名で出力され、XMLは生成済みのSQLが入れ替わります。ファイル名は記事中の例(Userテーブル)です。複雑な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種類を生成します。
targetRuntimeがMyBatis3なら、条件ビルダーの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ファイルが数秒で生まれる体験をすると、もう手書きには戻れなくなりますよ(笑)。
| REV. | DATE | 内容 |
|---|---|---|
| 3 | 2026-10-21 | 同じ説明の繰り返しを減らし、読みやすく整えた |
| 2 | 2026-10-15 | 図解を描き直し(図面のデザインにそろえた) |
| 1 | 2026-07-16 | 初版 |





