MyBatis Generatorで生成したMapperで "Invalid bound statement (not found)" というエラーが出た場合の対処法

# 概要

MyBatis Generatorで生成したMapperを呼び出そうとしたところ、以下のようなエラーが出ました：

```
There was an unexpected error (type=Internal Server Error, status=500).
Invalid bound statement (not found): com.example.demo.dao.FileTypeMapper.selectByExample
org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.example.demo.dao.FileTypeMapper.selectByExample
	at org.apache.ibatis.binding.MapperMethod$SqlCommand.<init>(MapperMethod.java:235)
...
```

この記事では、このエラーが出る原因と解決方法について調べた結果を共有します。

# 原因

Mapperインターフェース（`*Mapper.java`）とMapper XML（`*Mapper.xml`）のクラスパスが一致していない場合に、上のようなエラーが出てしまうようです。

このことが公式ドキュメントに書かれていないか調べてみたのですが、以下のあたりが該当しているのでしょうか・・・（？）

> http://mybatis.org/spring/mappers.html
> If the UserMapper has a corresponding MyBatis XML mapper file in the same classpath location as the mapper interface, it will be parsed automatically by the `MapperFactoryBean`. There is no need to specify the mapper in a MyBatis configuration file unless the mapper XML files are in a different classpath location. 

自分の環境でエラーが出た原因ですが、MySQLで以下のようなデータベースを作成し・・・

```sql:schema.sql
CREATE TABLE DEMODB.FILE_TYPE (
    TYPE_ID INT NOT NULL PRIMARY KEY,
    NAME VARCHAR(256) NOT NULL
);
CREATE TABLE DEMODB.FILE (
    TYPE_ID INT NOT NULL PRIMARY KEY,
    NAME VARCHAR(256) NOT NULL,
    CONTENT LONGBLOB NOT NULL
);
```

・・・そして、上のデータベースに対して、MyBatis Generatorの`generatorConfig.xml`を以下のように設定してMapperを生成していました。

```xml:generatorConfig.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
  PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
  "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">

<generatorConfiguration>
	<classPathEntry
		location="C:\Users\hiroki\.m2\repository\com\mysql\mysql-connector-j\8.0.31\mysql-connector-j-8.0.31.jar" />

	<context id="MySQLTables" targetRuntime="MyBatis3">
		<commentGenerator>
			<property name="suppressDate" value="true" />
		</commentGenerator>

		<jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"
			connectionURL="jdbc:mysql://localhost:3306/DEMODB" userId="dev"
			password="password1234">
		</jdbcConnection>

		<javaTypeResolver>
			<property name="forceBigDecimals" value="false" />
		</javaTypeResolver>

		<javaModelGenerator
			targetProject="mybatis-generator-example/src/main/java"
			targetPackage="com.example.demo.model">
			<property name="enableSubPackages" value="true" />
			<property name="trimStrings" value="true" />
		</javaModelGenerator>

		<sqlMapGenerator
			targetProject="mybatis-generator-example/src/main/resources"
			targetPackage="xml">
			<property name="enableSubPackages" value="true" />
		</sqlMapGenerator>

		<javaClientGenerator type="XMLMAPPER"
			targetProject="mybatis-generator-example/src/main/java"
			targetPackage="com.example.demo.dao">
			<property name="enableSubPackages" value="true" />
		</javaClientGenerator>

		<table schema="DEMODB" tableName="FILE_TYPE">
			<property name="useActualColumnNames" value="true" />
		</table>
		<table schema="DEMODB" tableName="FILE">
			<property name="useActualColumnNames" value="true" />
		</table>
	</context>
</generatorConfiguration>
```

ここで、`generatorConfig.xml`の中で
```
sqlMapGenerator.targetPackage="xml"
javaClientGenerator.targetPackage="com.example.demo.dao"
```
となっており、両者が一致していないため、エラーが出たようです。

# 解決方法

解決方法は２つあります。

1. `generatorConfig.xml`で`targetPackage`の値を一致させる。
1. `application.properties`でMapperの場所を明示的に指定する。

これらの方法をそれぞれ解説していきます。

## 1. `generatorConfig.xml`で`targetPackage`の値を一致させる

以下のように、`generatorConfig.xml`の中で`sqlMapGenerator`と`javaClientGenerator`の`targetPackage`の値が一致するように修正します。
その後、再びMyBatis Generatorを実行してMapperを再生成すると、最初に載せたエラーが出なくなります。

具体的には、`generatorConfig.xml`を以下のように修正します。

```xml:generatorConfig.xml
...
<sqlMapGenerator
    targetProject="mybatis-generator-example/src/main/resources"
    targetPackage="com.example.demo.dao">        <-- ここを一致させる
    <property name="enableSubPackages" value="true" />
</sqlMapGenerator>

<javaClientGenerator type="XMLMAPPER"
    targetProject="mybatis-generator-example/src/main/java"
    targetPackage="com.example.demo.dao">        <-- ここを一致させる
    <property name="enableSubPackages" value="true" />
</javaClientGenerator>
...
```

## 2. `application.properties`でMapperの場所を明示的に指定する

`generatorConfig.xml`で指定した`sqlMapGenerator.targetPackage`の場所を、`application.properties`の`mybatis.mapper-locations`で指定します。

具体的には、以下のように設定します。

```xml:generatorConfig.xml
...
<sqlMapGenerator
    targetProject="mybatis-generator-example/src/main/resources"
    targetPackage="xml">        <-- このようにパスを指定した場合・・・
    <property name="enableSubPackages" value="true" />
</sqlMapGenerator>

<javaClientGenerator type="XMLMAPPER"
    targetProject="mybatis-generator-example/src/main/java"
    targetPackage="com.example.demo.dao">
    <property name="enableSubPackages" value="true" />
</javaClientGenerator>
...
```

```:application.properties
mybatis.mapper-locations:classpath*:xml/*.xml        <-- このように記載する
```