概要
MyBatisの中で最も強力な機能の一つにresultMapがあります。
resultMapはSQLの結果をJavaのクラスにマッピングする際に利用され、実に柔軟でかつ手軽に利用できます。
また、resultMapは<resultMap>
内にMyBatis既定のタグを構造的に記述することで、複雑なJavaオブジェクトでもマッピングを可能にしてくれます。ただし記述には一定のルールがあるため、フレームワーク特有のルールに従った記述が必要です。
この投稿では、いくつかあるMyBatisの記述ルールの内、記述順序について説明します。
※当記事は.xml形式のMapperを記述すること想定してます。
resultMap内の記述ルール
必ず以下の順序で記述する必要があります。
<constructor>
-
<id>
もしくは<idArg>
<result>
<association>
<collection>
<discriminator>
例
例えば、次の場合はエラーとなります。
なぜなら、<id>
と<result>
の記述順序が逆であるためです。
<resultMap id="detailedBlogResultMap" type="Blog">
<result property="username" column="author_username"/>
<id property="id" column="author_id"/>
</resultMap>
この場合、次のように修正する必要があります。
<id>
と<result>
の順序を入れ替えます。
<resultMap id="detailedBlogResultMap" type="Blog">
<id property="id" column="author_id"/>
<result property="username" column="author_username"/>
</resultMap>
エラー
記述順序が逆である場合は、次のようなエラーが投げられます。
このエラーが確認された場合は、MyBatisの内の記述順序を疑ってみて下さい。
Caused by: org.xml.sax.SAXParseException: The content of element type "resultMap" must match "(constructor?,id*,result*,association*,collection*,discriminator?)".
その他の例
続けて、NGと修正のパターンをいくつか例示します。
本質的には上記で説明した内容と重複しますが、いくつかのパターンを用意しましたので実装時に参考になれば幸いです。
例1
<collection>
と<association>
の順序が逆なためNG
<resultMap id="detailedBlogResultMap" type="Blog">
<idArg column="blog_id" javaType="int"/>
<result property="title" column="blog_title"/>
<collection property="tags" ofType="Tag" >
<id property="id" column="tag_id"/>
</collection>
<association property="author" javaType="Author">
<id property="id" column="author_id"/>
<result property="username" column="author_username"/>
</association>
</resultMap>
<resultMap id="detailedBlogResultMap" type="Blog">
<idArg column="blog_id" javaType="int"/>
<result property="title" column="blog_title"/>
- <collection property="tags" ofType="Tag" >
- <id property="id" column="tag_id"/>
- </collection>
<association property="author" javaType="Author">
<id property="id" column="author_id"/>
<result property="username" column="author_username"/>
</association>
+ <collection property="tags" ofType="Tag" >
+ <id property="id" column="tag_id"/>
+ </collection>
</resultMap>
例2
<collection>
内の<association>
が<id>
と<result>
より上にあるためNG
<resultMap id="detailedBlogResultMap" type="Blog">
<id property="id" column="author_id"/>
<collection property="posts" ofType="Post">
<association property="author" javaType="Author"/>
<id property="id" column="post_id"/>
<result property="subject" column="post_subject"/>
<collection property="comments" ofType="Comment">
<id property="id" column="comment_id"/>
</collection>
<discriminator javaType="int" column="draft">
<case value="1" resultType="DraftPost"/>
</discriminator>
</collection>
</resultMap>
<resultMap id="detailedBlogResultMap" type="Blog">
<id property="id" column="author_id"/>
<collection property="posts" ofType="Post">
- <association property="author" javaType="Author"/>
<id property="id" column="post_id"/>
<result property="subject" column="post_subject"/>
+ <association property="author" javaType="Author"/>
<collection property="comments" ofType="Comment">
<id property="id" column="comment_id"/>
</collection>
<discriminator javaType="int" column="draft">
<case value="1" resultType="DraftPost"/>
</discriminator>
</collection>
</resultMap>
参考資料
- MyBatis – MyBatis 3 | Mapper XML ファイル https://mybatis.org/mybatis-3/ja/sqlmap-xml.html