mybatis-spring-boot-starter 2.1の変更点

2019年7月15日にリリースした2.1の変更点をまとめました。
この変更では、既にEOLを迎えているSpring Boot 2.0.xへのサポートがなくなり、Spring Boot 2.1以上が必要になります。

なお、

* mybatis-spring-boot-starterの使い方については、[こちら](http://qiita.com/kazuki43zoo/items/ea79e206d7c2e990e478)（バージョン2.1対応済）
* mybatis-spring-boot-starter 1.3から2.0の変更点については、[こちら](https://qiita.com/kazuki43zoo/items/38a24e051359e39c012c)
* mybatis-spring-boot-starter 1.2から1.3の変更点については、[こちら](https://qiita.com/kazuki43zoo/items/3f94d2049d331f81e6f5)
* mybatis-spring-boot-starter 1.1から1.2の変更点については、[こちら](http://qiita.com/kazuki43zoo/items/84b4a89846a7d0d65922)
* mybatis-spring-boot-starter 1.0から1.1の変更点については、[こちら](http://qiita.com/kazuki43zoo/items/5c46ac2f539d365aa53b)

も必要に応じて合わせてご覧下さい。

> **NOTE:**
>
> ちなみに、mybatis-spring-boot-starter 2.0.xのメンテナンスは基本的には終了になります（致命的なバグなどが報告されたタイミングでパッチの提供要否を検討しますが、基本的にはバージョンアップを提案させてもらいます）。
>
> また、Spring Boot 1.5.x(Spring Framework 4.3.x)向けのメンテナンスはバージョン1.3.xで継続していますが、2019/8を目処にSpring Boot 1.5.xがEOLになることがアナウンスされているので、バージョン1.3.xのメンテナンスも同じ時期に終了する予定です(＝最後に1.3.5をリリースしてメンテナンスを終了する予定)。

本バージョンにはバグが存在することが報告されているため、バグの発生条件に一致する場合は回避策を適用する必要があります。なお、バグについては、2019年10月中旬あたりにリリース予定のmybatis-spring-boot-starter 2.1.1(mybtis-spring 2.0.3)で修正されます。（2019/7/21追記）

* `Class` を引数にとるコンストラクタを使ってインスタンスを生成する`TypeHandler`をパッケージ指定でスキャンすることができない（詳細は「[gh-370](https://github.com/mybatis/spring-boot-starter/issues/370)」と「[mybatis-spring/gh-394](https://github.com/mybatis/spring/issues/394)」を参照） 

# 依存ライブラリの必須バージョン

* MyBatis 3.5+
* Mybatis-Spring 2.0+
* **Spring Boot 2.1+**

# Javaの必須バージョン

* Java 8+

# 依存ライブラリのバージョン更新

バージョン2.1では、以下のライブラリのバージョンが更新されています。

| ライブラリ名 | 2.0.1のバージョン | 2.1.0のバージョン | 補足 |
| --------- | -------------- | -------------- | --- |
| MyBatis | 3.5.1 | **3.5.2** | - |
| MyBatis Spring | 2.0.1 | **2.0.2** | API上の互換性としては、MyBatis Spring 2.0+であれば動作はしますが、**全ての機能を利用する場合は2.0.2+が必要** |
| MyBatis Velocity(Optional) | - | **2.1.0** | API上の互換性は2.1.0より前でも動作しますが、**全ての機能を利用する場合は2.1.0+が必要** |
| MyBatis Freemarker(Optional) | - | **1.2.0** | API上の互換性は1.2.0より前でも動作しますが、**全ての機能を利用する場合は1.2.0+が必要** |
| MyBatis Thymeleaf(Optional) | - | **1.0.1** | |
| Spring Boot | 2.0.9.RELEASE | **2.1.6.RELEASE** | TravisCIで2.2.0-SNAPSHOTを使用したテストも実施済 |

# `LanguageDriver`の自動検出

DIコンテナに登録されている `LanguageDriver` を自動で検出してMyBatisへ適用する仕組みをサポートしました。
この対応により、開発者が独自に作成した `LanguageDriver` クラスは、以下のようにBean定義すればMyBatisに適用することができます。

```java:独自のLanguageDriverのBean定義例
@Bean
MyLanguageDriver myLanguageDriver() {
  return MyLanguageDriver();
}
```

さらに、DIコンテナから検出した `LanguageDriver` のBeanが１つの場合は、検出した `LanguageDriver` がデフォルトの `LanguageDriver` クラスとして扱われます（複数のBeanを検出した場合は、MyBatis本体のデフォルト設定である `XMLLanguageDriver` がそのまま適用されます）。自動検出機能によってデフォルトの `LanguageDriver` クラスを変更したくない場合や、複数の `LanguageDriver` を共存して利用する際にデフォルトの `LanguageDriver` クラスを変更したい場合は、 次に紹介する `mybatis.default-scripting-language-driver` プロパティ(バージョン2.1で追加したプロパティ)を使用して、デフォルトの `LanguageDriver` クラスを明示的に指定するようにしてください。

# `mybatis.default-scripting-language-driver`の追加

バージョン2.0までは、デフォルトで使う `LanguageDriver` クラスを指定する方法として、 `mybatis.configuration.default-scripting-language` というプロパティ(MyBatis本体が提供するコンフィギュレーションクラスへ直接値を設定するためのプロパティ)をサポートしていましたが、後述の「`LanguageDriver`の自動コンフィグレーションのサポート」と組み合わせた時に期待通りの動作にならない事があるため、このプロパティは廃止（使用禁止）し、新たに `mybatis.default-scripting-language-driver` を追加しました。

```properties
mybatis.default-scripting-language-driver={デフォルトのLanguageDriverクラスのFQCN}
```

# `LanguageDriver`の自動コンフィグレーションのサポート

MyBatis純正の以下の３つのサブモジュール（`LanguageDriver`）に対して、自動コンフィギュレーションの仕組みをサポートしました。

* [mybatis-velocity](https://github.com/mybatis/velocity-scripting)
* [mybatis-freemarker](https://github.com/mybatis/freemarker-scripting)
* [mybatis-thymeleaf](https://github.com/mybatis/thymeleaf-scripting)

上記３つのサブモジュールのjarファイルをクラスパス上に追加すると、自動でサブモジュール提供の `LanguageDriver` クラスのBeanがDIコンテナに登録されてMyBatisへ適用されます。なお、開発者が明示的に上記サブモジュールから提供されている`LanguageDriver`クラスをBean定義した場合は、自動コンフィギュレーションは行われません。

> **WARNING:**
>
> 以下の条件に全て一致する場合は、下位互換性が失われるため、追加で対策が必要になります。
> 
> * 上記３つのサブモジュール(mybatis-velocity, mybatis-freemarker, mybatis-thymeleaf)のjarが１つ**のみ**クラスパス上にある
> * デフォルトの `LanguageDriver` がサブモジュール提供の`LanguageDriver`では**ない**
>
> 条件に一致する場合は、サブモジュール提供の`LanguageDriver`クラスがデフォルトの `LanguageDriver` に設定される仕組みになっているため、以下のように明示的にデフォルトの `LanguageDriver` を指定する必要があります。
>
> ```properties
> mybatis.default-scripting-language-driver={デフォルトのLanguageDriverクラスのFQCN}
> ```


## MyBatis Velocityの利用

以下のアーティファクトを追加すると、`org.mybatis.scripting.velocity.VelocityLanguageDriver`(mybatis-velocity 2.0以前を指定すると`org.mybatis.scripting.velocity.Driver`)をMyBatisへ適用します。

```xml:pom.xml
<!-- Mybatis Velocityを利用する場合 -->
<dependency>
  <groupId>org.mybatis.scripting</groupId>
  <artifactId>mybatis-velocity</artifactId>
  <version>2.1.0</version>
</dependency>
```

mybatis-velocity 2.1.0以降を利用する場合は、コンフィギュレーションプロパティの仕組みを利用してMyBatis VelocityおよびMyBatis Velocityの中で利用するVelocityのテンプレートエンジンの動作をカスタマイズすることができます。

```properties:src/main/resources/application.properties
#
# mybatis.scripting-language-driver.velocity.{key} = {value} 形式
#

# Velocity本体の動作をカスタマイズするプロパティ
# mybatis.scripting-language-driver.velocity.velocity-settings.{name} = {value}形式
# {name}に設定可能なプロパティはリファレンスドキュメントを参照してください。
mybatis.scripting-language-driver.velocity.velocity-settings.runtime.custom_directives = com.example.directives.MyDirective

# テンプレートエンジンに渡す追加属性(オブジェクト)を指定するプロパティ
# mybatis.scripting-language-driver.velocity.additional-context-attributes.{name} = {value}
mybatis.scripting-language-driver.velocity.additional-context-attributes.likeEscape = com.example.helpers.LikeEscape
```

## MyBatis FreeMarkerの利用

以下のアーティファクトを追加すると、`org.mybatis.scripting.freemarker.FreeMarkerLanguageDriver`をMyBatisへ適用します。

```xml:pom.xml
<dependency>
  <groupId>org.mybatis.scripting</groupId>
  <artifactId>mybatis-freemarker</artifactId>
  <version>1.2.0</version>
</dependency>
```

mybatis-velocity 1.2.0以降を利用する場合は、コンフィギュレーションプロパティの仕組みを利用してMyBatis FreeMarkerおよびMyBatis FreeMarkerの中で利用するFreeMarkerのテンプレートエンジンの動作をカスタマイズすることができます。

```properties:src/main/resources/application.properties
#
# mybatis.scripting-language-driver.freemarker.{key} = {value} 形式
#

# FreeMarker本体の動作をカスタマイズするプロパティ
# mybatis.scripting-language-driver.freemarker.freemarker-settings.{name} = {value}形式
# {name}に設定可能なプロパティはリファレンスドキュメントを参照してください。
mybatis.scripting-language-driver.freemarker.freemarker-settings.interpolation_syntax = dollar

# MyBatis FreeMarkerの動作をカスタマイズするプロパティ
# mybatis.scripting-language-driver.freemarker.{name} = {value}
# {name}に設定可能なプロパティはリファレンスドキュメントを参照してください。
mybatis.scripting-language-driver.freemarker.template-file.base-dir = sql
```


## MyBatis Thymeleafの利用

以下のアーティファクトを追加すると、`org.mybatis.scripting.thymeleaf.ThymeleafLanguageDriver`をMyBatisへ適用します。

```xml:pom.xml
<dependency>
  <groupId>org.mybatis.scripting</groupId>
  <artifactId>mybatis-thymeleaf</artifactId>
  <version>1.0.1</version>
</dependency>
```

コンフィギュレーションプロパティの仕組みを利用してMyBatis ThymeleafおよびMyBatis Thymeleafの中で利用するThymeleafのテンプレートエンジンの動作をカスタマイズすることができます。

```properties:src/main/resources/application.properties
#
# mybatis.scripting-language-driver.thymeleaf.{key} = {value} 形式
#

# MyBatis Thymeleafの動作をカスタマイズするプロパティ
# mybatis.scripting-language-driver.thymeleaf.{name} = {value}
# {name}に設定可能なプロパティはリファレンスドキュメントを参照してください。
mybatis.scripting-language-driver.thymeleaf.use2way = false
mybatis.scripting-language-driver.thymeleaf.template-file.cache-enabled = false
mybatis.scripting-language-driver.thymeleaf.dialect.like-additional-escape-target-chars = ％, ＿
```

# Mapperの遅延初期化制御のサポート

DIコンテナに登録したMapperの初期化タイミング（DIコンテナ初期化時、インジェクションまたは利用時）を制御するためのオプションをサポートしました。デフォルトの動作は、DIコンテナ初期化時に全てのMapperが初期化されます。

このオプションは、Spring Boot 2.2(投稿時点では正式版は未リリース)でサポートされるBeanの遅延初期化の仕組みを有効化した際に、特定の条件下においてMapprのメソッド呼び出し時にエラーが発生してしまうため、Mapperに対する遅延初期化の適用有無を利用者側で制御できるようにするために追加しました。エラーを回避するだけなら、Mapperに対する遅延初期化を無条件で無効化すればよいのですが、開発時（テスト時）には遅延初期化の仕組みは有効だと思うので、MyBatis(mybatis-spring & mybatis-spring-boot-starter)独自にMapperを遅延初期化を制御できるようにしました。詳しくは、「[mybatis-spring-boot 2.1.0で追加されるmybatis.lazy-initializationについて](https://qiita.com/kazuki43zoo/items/3d131abffc1f37dc9352)」をご覧ください。

> **NOTE:**
>
> 本バージョンで提供する遅延初期化の仕組みはMyBatis(mybatis-spring & mybatis-spring-boot-starter)独自の仕組みなので、Spring Boot 2.1系でも利用することができます。

# `TypeHandler`の自動検出

DIコンテナに登録されている `TypeHandler` を自動で検出してMyBatisへ適用する仕組みをサポートしました。
この対応により、開発者が独自に作成した `TypeHandler` クラスは、以下のようにBean定義すればMyBatisに適用することができます。

```java:独自のTypeHandlerのBean定義例
@Bean
MyTypeHandler myTypeHandler() {
  return MyTypeHandler();
}
```

# Mapperスキャンの無効化条件に`MapperScannerConfigurer`を追加

開発者が明示的にMapperをDIコンテナへ登録するための定義を行っている場合、mybatis-spring-boot-startはMapperの自動スキャンを無効化するようになっています。バージョン2.0までは、以下の条件のいずれかに一致した場合に自動スキャンが無効化されていました。

* コンフィギュレーションクラスに`@MapperScan`を指定
* XMLコンフィギュレーションに`<mybatis:scan>`を指定
* `MapperFactoryBean`のBeanを定義

バージョン2.1では、上記に加え、

* `MapperScannerConfigurer`のBeanを定義

した際にもMapperの自動スキャンが無効化になります。


# 「タイプエイリアスをスキャンする際に重複エラーが発生する不具合」の修正

バージョン2.0.1が依存するmybatis-spring 2.0.1には、特定の条件下において「[タイプエイリアスをスキャンする際に重複エラーが発生する不具合](https://qiita.com/kazuki43zoo/items/38a24e051359e39c012c#%E3%83%99%E3%83%BC%E3%82%B9%E3%83%91%E3%83%83%E3%82%B1%E3%83%BC%E3%82%B8%E6%8C%87%E5%AE%9A%E6%99%82%E3%81%AE%E3%83%AF%E3%82%A4%E3%83%AB%E3%83%89%E3%82%AB%E3%83%BC%E3%83%89%E3%82%92%E3%82%B5%E3%83%9D%E3%83%BC%E3%83%88)」がありましたが、バージョン2.1.0が依存するmybatis-spring 2.0.2で修正されています。

# `@MybatisTest`に`properties`属性を追加

`@MybatisTest`にプロパティ(key=value形式)を指定するための属性(`properties`)を追加しました。この対応により、テスト時にのみ適用したいプロパティがあった場合に、`@TestPropertySource`を使う必要がなくなります。なお、この対応は、Spring Boot 2.1で`@JdbcTest`に追加された仕組みを、`@MybatisTest`にフィードバックしたものです。

```java
@MybatisTest(properties = {
  "logging.level.org.springframework.jdbc=debug",
  "spring.datasource.schema=classpath:TodoMapperTests/schema.sql"
  })
public class TodoMapperTests {
  // ...
}
```

# ドキュメントのソースファイルをXDOCからMarkdownへ変更

Maven Site Pluginを使って生成しているリファレンスドキュメントのソースファイルをXDOC形式からMarkdown形式に変更しました。ソースファイルの形式を変えただけなので、ドキュメントの内容は基本的には同じ（2.1.0でサポートした変更内容の適用部分以外は同じ）なのですが・・・「ソースコードのコードハイライト」がなくなっています（Markdown使用時の制約なのか？それともPluginの使い方が正しくないのか？は現在調査中です）。

この対応により、ビルド後のドキュメントからはコードハイライトがなくなってしまいましたが、Markdown形式にすることで最新のドキュメント(＝スナップショットバージョンのドキュメント)をGitHub経由で参照することができるようになりました（＝このメリットを優先してXDOC形式からMarkdown形式に変更しました）。

* [mybatis-spring-boot-autoconfigure](https://github.com/mybatis/spring-boot-starter/blob/master/mybatis-spring-boot-autoconfigure/src/site/markdown/index.md)
* [mybatis-spring-boot-test-autoconfigure](https://github.com/mybatis/spring-boot-starter/blob/master/mybatis-spring-boot-test-autoconfigure/src/site/markdown/index.md)



# 簡易サンプルの追加

バージョン2.1にて、結合テストの充実化も兼ねて[サンプル](https://github.com/mybatis/spring-boot-starter/tree/master/mybatis-spring-boot-samples)のバリエーションを増やしました。

## `LanguageDriver`関連

| サンプルプロジェクト名 | 説明 | 
| --------- | --------------- |
| [mybatis-spring-boot-sample-velocity](https://github.com/mybatis/spring-boot-starter/tree/master/mybatis-spring-boot-samples/mybatis-spring-boot-sample-velocity) | MyBatis Velocity 2.1+ベースの簡易サンプルプロジェクト |
| [mybatis-spring-boot-sample-velocity-legacy](https://github.com/mybatis/spring-boot-starter/tree/master/mybatis-spring-boot-samples/mybatis-spring-boot-sample-velocity-legacy) | MyBatis Velocity 2.0ベースの簡易サンプルプロジェクト |
| [mybatis-spring-boot-sample-freemarker](https://github.com/mybatis/spring-boot-starter/tree/master/mybatis-spring-boot-samples/mybatis-spring-boot-sample-freemarker) | MyBatis FreeMarker 1.2+ベースの簡易サンプルプロジェクト |
| [mybatis-spring-boot-sample-velocity-legacy](https://github.com/mybatis/spring-boot-starter/tree/master/mybatis-spring-boot-samples/mybatis-spring-boot-sample-freemarker-legacy) | MyBatis FreeMarker 1.1.xベースの簡易サンプルプロジェクト |
| [mybatis-spring-boot-sample-thymeleaf](https://github.com/mybatis/spring-boot-starter/tree/master/mybatis-spring-boot-samples/mybatis-spring-boot-sample-thymeleaf) | MyBatis Thymeleaf の簡易サンプルプロジェクト |

## JVM言語関連

| サンプルプロジェクト名 | 説明 | 
| --------- | --------------- |
| [mybatis-spring-boot-sample-groovy](https://github.com/mybatis/spring-boot-starter/tree/master/mybatis-spring-boot-samples/mybatis-spring-boot-sample-groovy) | Groovyを利用した簡易サンプルプロジェクト |
| [mybatis-spring-boot-sample-kotlin](https://github.com/mybatis/spring-boot-starter/tree/master/mybatis-spring-boot-samples/mybatis-spring-boot-sample-kotlin) | Kotlinを使用した簡易サンプルプロジェクト |