Java
MyBatis
java8
SpringBoot

Mybatisでcollectionを指定するときの注意点

Mybatisを使っていると、ドメインモデルとしてのクラスとデータベースのテーブルを分離して設計できるので、非常に便利である。

XMLファイルを記述しておくことで、テーブルから参照したデータを指定したモデルクラスにマッピングしてくれるわけだが、collectionを設定した際に少々詰まってしまった。

調べ方が悪かったのかもしれないが、解決に時間がかかってしまったので、対応方法を書き残しておく。


バージョン情報


  • Java: 1.8.0_161

  • Springboot: 1.3.3


    • やや古いのは気にしないで……



  • Mybatis: 3.4.6


発生したエラー

下記はサンプルだが、こんな感じでモデルクラスとXMLを書いていた。

Pet の集合クラスとして Pets を用意し、 PersonPets を持たせている。


Person.java

    Name name;

Age age;
Pets pets;


Pets.java

    List<Pet> values;

public Pets() {
this.values = Collections.emptyList();
}


Person に相応するテーブルからデータを参照するために、下記のようにマッピング


PersonMapper.xml

    <resultMap id="net.tobachi.sample.model.Person">

<result property="name.values" column="name"/>
<result property="age.values" column="age"/>
<collection property="pets.values" resultMap="pet"/>
</resultMap>

<resultMap id="pet" type="net.tobachi.sample.model.Pet">
<result property="animalType.value" column="animal_type"/>
<result property="name.value" column="name"/>
<result property="age.value" column="age"/>
</resultMap>


しかし、これではうまくいかず UnsupportedOperationException が発生してしまった。

org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.exceptions.PersistenceException: 

### Error querying database. Cause: java.lang.UnsupportedOperationException
### The error may exist in net/tobachi/sample/datasource/model/PersonsMapper.xml
### The error may involve net.tobachi.sample.datasource.model.PersonsMapper.findBy
### The error occurred while handling results


対応

Pets クラスにデフォルトで持たせる空リストの生成処理を修正したところ、エラーが発生せず問題なく動作するようになった。


Pets.java

    List<Pet> values;

public Pets() {
this.values = new ArrayList<>();
}


どうやら Collections.emptyList() ではだめだったらしい。


原因

Collections.emptyList() の実装を見てみた。


Collections.java

    public static final List EMPTY_LIST = new EmptyList<>();

public static final <T> List<T> emptyList() {
return (List<T>) EMPTY_LIST;
}


ジェネリクスの型を特定しない形で空リストを返却しているように見える。

UnsupportedOperationException が発生していることから、 immutable なリストを返却するために発生しているっぽい。

これだとMybatisが上collectionを上手く扱ってくれないのだろう。


参照したページ

https://stackoverflow.com/questions/16534205/mybatis-java-lang-unsupportedoperationexception