Help us understand the problem. What is going on with this article?

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

More than 1 year has passed since last update.

2017年4月10日のリリースされた1.3の変更点をまとめました。

なお、

  • mybatis-spring-boot-starterの使い方については、こちら(バージョン1.3対応済)
  • mybatis-spring-boot-starter 1.1から1.2の変更点については、こちら
  • mybatis-spring-boot-starter 1.0から1.1の変更点については、こちら

をご覧下さい。

Note:
2017/8/21: 追記
バージョン1.3.1の変更点を追加しました。
2019/5/7: 追記
バージョン1.3.2, 1.3.3, 1.3.4の変更点を反映しました。

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

バージョン1.3を使う場合は、以下のバージョンが必須になります。

  • MyBatis 3.4+
  • Mybatis-Spring 1.3+
  • Spring Boot 1.5+

Spring Boot 1.5+が必須

バージョン1.3より、MyBatisの機能をテストする時に必要となるBean定義をサポートする@MybatisTestアノテーションが追加され、そのアノテーションがSpring Boot 1.5でサポートされたAPIに依存しているため、Spring Boot 1.5+が必須になります。なお、Spring Boot 1.4系でmybatis-spring-boot-starterを使う場合は、バージョン1.2系を使用してください。

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

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

ライブラリ名 1.2.0のバージョン 1.3.0のバージョン 1.3.1のバージョン 1.3.2のバージョン 1.3.3のバージョン 1.3.4のバージョン
MyBatis 3.4.2 3.4.4 3.4.5 3.4.6 3.4.6 3.4.6
MyBatis Spring 1.3.1 1.3.1 1.3.1 1.3.2 1.3.2 1.3.2
Spring Boot 1.4.3.RELEASE 1.5.2.RELEASE 1.5.6.RELEASE 1.5.10.RELEASE 1.5.19.RELEASE 1.5.20.RELEASE

Note:
バージョン1.3.0と同時にリリースされたバージョン1.2.1と比較すると、Spring Bootのバージョンだけ更新(1.4.5.RELEASE -> 1.5.2.RELEASE)されています。

ConfigurationCustomizerインタフェースの追加

MyBatisのコンフィギュレーション情報を保持するBean(org.apache.ibatis.session.ConfigurationのBean)を、Javaコードでカスタマイズするためのコールバックインタフェース(org.mybatis.spring.boot.autoconfigure.ConfigurationCustomizer)が追加されました。以下のように、このインタフェースを実装したクラスをBean定義しておくと、ConfigurationCustomizerconfigureメソッドがコールバックされる仕組みになっており、Javaコードを使用してMyBayisのコンフィギュレーションを完全にカスタマイズすることができます。

ラムダ式を使用したConfigurationCustomizerのBean定義例
@Configuration
public class MyBatisConfiguration {
    @Bean
    ConfigurationCustomizer mybatisConfigurationCustomizer() {
        return (configuration) -> {
            // aplication.propertiesで指定・表現できないカスタマイズコードを実装
            configuration.getTypeHandlerRegistry().register(RoundingMode.class, EnumOrdinalTypeHandler.class);
        };
    }
}

Note:

ConfigurationCustomizerインタフェースは、バージョン1.3.0と同時にリリースされたバージョン1.2.1にもバックポートされています。

@MybatisTest(mybatis-spring-boot-starter-test)の追加

バージョン1.3より、MyBatisの機能をテストする時に必要となるBean定義をサポートする@MybatisTestアノテーションが追加されました。これは、Spring Bootが提供する@DataJpaTest@JdbcTestのMyBatis版になります(当然ながら・・使い方もSpring Boot提供のアノテーションと同じです!!)。
この対応に伴い、MyBatisのテストをする際に必要となるライブラリ群を解決するためのmybatis-spring-boot-starter-testが新設されているので、MyBatis提供の機能に対するテストを行う場合は、pom.xmlに以下の定義を追加しましょう!!

pom.xml
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter-test</artifactId>
    <version>1.3.4</version>
    <scope>test</scope>
</dependency>

たとえば、以下のようなMapperインタフェースに対するテストを行う場合は、

src/main/java/com/example/mapper/TodoMapper.java
package com.example.mapper;

import com.example.domain.Todo;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Options;
import org.apache.ibatis.annotations.Select;

@Mapper
public interface TodoMapper {

    @Insert("INSERT INTO todo (title, details, finished) VALUES (#{title}, #{details}, #{finished})")
    @Options(useGeneratedKeys = true)
    void insert(Todo todo);

    @Select("SELECT id, title, details, finished FROM todo WHERE id = #{id}")
    Todo select(int id);

}

@MybatisTestを使用して、以下のようなテストケースクラスを作ればOKです。

src/main/java/com/example/mapper/TodoMapperTests.java
package com.example.mapper;

import com.example.domain.Todo;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mybatis.spring.boot.test.autoconfigure.MybatisTest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.test.context.junit4.SpringRunner;

import static org.assertj.core.api.Assertions.assertThat;

@RunWith(SpringRunner.class)
@MybatisTest // (1)
public class TodoMapperTests {

    @Autowired
    private TodoMapper todoMapper; // (2)

    @Autowired
    private NamedParameterJdbcOperations jdbcOperations; // (3)

    @Test
    public void insert() {

        // setup
        // none

        // perform test and assertions
        {
            // (4)
            Todo newTodo = new Todo();
            newTodo.setTitle("飲み会");
            newTodo.setDetails("銀座 19:00");
            todoMapper.insert(newTodo);

            // (5)
            Todo actualTodo =
                jdbcOperations.queryForObject("SELECT * FROM todo WHERE id = :id",
                    new MapSqlParameterSource("id", newTodo.getId()),
                    new BeanPropertyRowMapper<>(Todo.class));
            assertThat(actualTodo.getId()).isEqualTo(newTodo.getId());
            assertThat(actualTodo.getTitle()).isEqualTo("飲み会");
            assertThat(actualTodo.getDetails()).isEqualTo("銀座 19:00");
            assertThat(actualTodo.isFinished()).isEqualTo(false);
        }
    }


    @Test
    public void select() {

        // (6)
        // setup
        Todo newTodo = new Todo();
        newTodo.setTitle("飲み会");
        newTodo.setDetails("銀座 19:00");

        GeneratedKeyHolder keyHolder = new GeneratedKeyHolder();
        jdbcOperations.update(
            "INSERT INTO todo (title, details, finished) VALUES(:title, :details, :finished)",
            new BeanPropertySqlParameterSource(newTodo), keyHolder);

        // perform test and assertions
        {
            // (7)
            Todo actualTodo = todoMapper.select(keyHolder.getKey().intValue());

            assertThat(actualTodo.getId()).isEqualTo(keyHolder.getKey().intValue());
            assertThat(actualTodo.getTitle()).isEqualTo("飲み会");
            assertThat(actualTodo.getDetails()).isEqualTo("銀座 19:00");
            assertThat(actualTodo.isFinished()).isEqualTo(false);
        }
    }

}
項番 説明
(1) クラスに@MybatisTestを付与する。このアノテーションを付与することで、MyBatisを動かすために必要になるAutoConfigureクラスだけが有効になります。デフォルトの動作ではコンポーネントスキャンが無効化されているので、テスト時に必要ないBeanが無題にDIコンテナに登録されることを防ぐことができます。
(2) テスト対象のMapperをインジェクションする。@MybatisTestを付与すると、MyBatis提供のAutoConfigureによってMapperのBeanが生成されます。
(3) 登録データの検証およびテストデータを登録するために、NamedParameterJdbcTemplate のBeanをインジェクションする。@MybatisTestを付与すると、JdbcTemplateNamedParameterJdbcTemplateのBeanがDIコンテナに登録されます。
(4) テスト対象のinsertメソッドを呼び出す。
(5) insertメソッドの呼び出し結果を検証する。ここでは、NamedParameterJdbcOperationsのメソッドを介して登録したデータを取得し、登録したデータの妥当性を検証しています。
(6) selectメソッドのテストを行うためにテストデータを登録する。ここでは、NamedParameterJdbcOperationsのメソッドを介してテストデータを登録しています。なお、Spring Framework提供の@Sqlアノテーションなどを使用してテストデータを登録する方法もあります。
(7) テスト対象のselectメソッドを呼び出す。
(8) selectメソッドの呼び出し結果を検証する。

この状態でテストを実行すると、上位パッケージに存在するSpring Bootアプリケーションクラス(@SpringBootApplicationを付与したクラス)内で定義しているBean定義も読み込まれる仕組みになっているため、MyBatisのテストに必要ないBeanがDIコンテナに登録される可能性があります。
もし、MyBatisのテストに必要ないBeanをDIコンテナに登録したくない場合は、テストケースクラスと同じパッケージに以下のような空のSpring Bootアプリケーションクラスを作成してください。こうすることで、上位パッケージにあるSpring Bootアプリケーションクラスを無効化することができます。

src/test/java/com/example/mapper/MapperTestApplication.java
package com.example.mapper;

import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class MapperTestApplication {

}

さらに詳しい情報は、公式リファレンスおよびSpring Bootが提供する@DataJpaTest@JdbcTestのリファレンスをご覧ください。

Note:
@MybatisTestアノテーション(およびmybatis-spring-boot-starter-test)は、バージョン1.3と同時にリリースされたバージョン1.2.1にもバックポートされています。

IDE上でのプロパティ値の入力補完改善

1.3.0までは、一部のプロパティ(mybatis.configuration.default-scripting-language)に対する入力補完が効かない状態になっていましたが、Spring Bootが提供する「Adding additional meta-data」の仕組みを利用することで、1.3.1より入力補完が効くように改善されています。

コンフギュレーションプロパティでtypeAliasesSuperTypeの指定をサポート

バージョン2.0の変更点を参照してください。(バージョン1.3.3よりサポート)

kazuki43zoo
Javaエンジニアで、SpringやMyBatisらへんにそれなりに詳しいです。お仕事のつながりで「Spring徹底入門 Spring FrameworkによるJavaアプリケーション開発」を共著させてもらいました!
https://kazuki43zoo.github.io
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away