なんとな~くしあわせ?の日記

JavaとかAWSの設定とかをメモする技術ブログ

MyBatisエラー別対応とか

Wikiの方に書いた記事によくアクセスがあるようなので、はてなに移しておく。

MyBatisのエラー別対応

エラーメッセージ:"Mapped Statements collection does not contain value for クラス名"

原因

  • ディレクトリ構成が変
  • Mapperファイルに対応するソースファイルを用意していない、またはその逆

ここのサイトに詳しいトラブルシュートが書いてある

ameblo.jp

引用

たぶん設定で変えられると思うのですが、Mavenではリソースの配置場所が最初からあらかじめ決められています。javaのソースファイルはsrc/main/java配下に、それ以外のリソースはsrc/main/resources配下に。他にもいろいろ決まっているので、気になる方はここ(Introduction to the Standard Directory Layout)を参照してください。つまり、classファイル出力先でjavaxmlを一緒にしたい場合、src/main/java配下にHogeMapper.javaを作成したら、src/main/resources配下にHogeMapper.xmlを置く必要があったわけでした。

  • 上記の場合は、Mavenで決められてるソースファイルやリソースファイルのディレクトリ仕様に従っていないから出るエラーでした。
  • あとはおそらく、Mapperファイルに対応するソースファイルを用意していない、またはその逆をやらかした時に出るエラー

このディレクトリ仕様に関する話はどうやらMyBatisのドキュメントの方には書いてないようです。まあMyBatisのデベロッパーたちもまさかそんな間違いをされるとは思ってなかったのかも(そうしないでも動くことは動く)

エラーメッセージ:"Mapped Statements collection already contains value for クラス名"

原因

  • Mapperファイルの二重読み込み

上とは逆の話

stackoverflow.com

MyBatisは実行時にクラスパス上にあるすべてのXMLファイル(Mapper)を見ようとする。eclipseなどのIDEを使っている場合、生成された余計なクラスファイルを見に行った結果、2重にXMLを読み込んでいることがある。

XMLファイルの指定は様々だが、MyBatis+Springならば例えばこう

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="configLocation" value="/WEB-INF/config/mybatis-config.xml" />
    <property name="mapperLocations" value="/WEB-INF/classes/your/package/name/*.xml" />
</bean>

Mapper用のXMLファイルがMavensrc/main/resources以下に配置されていたものとする。その場合、Mavenビルドのシーケンス上 compileフェイズで target/classes 以下にクラスファイルとXMLファイルが吐かれる。同様にして、{生成されたアプリ名}/WEB-INF/classes/your/package/name/*.xml上にもマッパーファイルが吐きだされる。eclipseのJettyプラグインなどでこれを実行すると、本来は後者のXMLファイルのみを読み込むことを想定しているのだが、前者のXMLも後から読み込まれるのでこのエラーが出る。どちらかというとeclipseが余計なおせっかいをしている印象だ。とりあえずclassesディレクトリを削除してアプリを動かすと問題なく動くようになる。

まとめ

  • Mavenのビルドファイルは開発の本筋とは関係ないけど、知っておくといろいろ便利なのでXML、書こう!