MyBatisがサポートするJDBCデータ型
MyBatisは以下のJDBCデータ型をサポートしています。jdbcType属性で指定する際は、列挙型の値を大文字で記述する必要があります。
| データ型 | データ型 | データ型 | データ型 | データ型 | データ型 |
|---|---|---|---|---|---|
| BIT | FLOAT | CHAR | TIMESTAMP | OTHER | UNDEFINED |
| TINYINT | REAL | VARCHAR | BINARY | BLOB | NVARCHAR |
| SMALLINT | DOUBLE | LONGVARCHAR | VARBINARY | CLOB | NCHAR |
| INTEGER | NUMERIC | DATE | LONGVARBINARY | BOOLEAN | NCLOB |
| BIGINT | DECIMAL | TIME | NULL | CURSOR | ARRAY |
ResultMapの構成要素
- constructor: オブジェクトのインスタンス化時に、結果をコンストラクタに注入する。
- idArg: IDとして扱われる引数。パフォーマンス向上に役立つ。
- arg: コンストラクタに注入される通常の引数。
- id: IDとして扱われるプロパティ。パフォーマンス向上に役立つ。
- result: フィールドまたはJavaBeanプロパティに注入される通常の結果。
- association: 複雑な関連オブジェクトをマッピングする。
- collection: 複雑なオブジェクトのコレクションをマッピングする。
- discriminator: 結果の値に基づいて、使用するResultMapを決定する。
1. 基本のidとresultマッピング
プロパティ名とカラム名のマッピング、データ型の指定を行います。jdbcType属性は前述の表に従い、必ず大文字で指定します。
<id property="identifier" column="user_id"/>
<result property="userName" column="name" jdbcType="VARCHAR"/>
2. コンストラクタを用いたマッピング
コンストラクタ引数の順序に基づいてマッピングを行います。IDプロパティにはプリミティブ型のintではなく、ラッパークラスのIntegerを使用することを推奨します。
Javaクラス例:
public class UserAccount {
private Integer userId;
private String accountName;
private String profile;
public UserAccount(Integer userId, String accountName, String profile) {
this.userId = userId;
this.accountName = accountName;
this.profile = profile;
}
}
XMLマッピング例:
<resultMap id="userResultMap" type="UserAccount">
<constructor>
<idArg column="user_id" javaType="int"/>
<arg column="account_name" javaType="String"/>
<arg column="profile" javaType="String"/>
</constructor>
</resultMap>
コンストラクタ引数の名前でマッピングすることも可能です。その場合、順序は影響しません。以下の2つの方法があります。
方法1: @Paramアノテーションの使用
public UserAccount(@Param("userId") Integer userId,
@Param("accountName") String accountName,
@Param("profile") String profile) {
this.userId = userId;
this.accountName = accountName;
this.profile = profile;
}
<resultMap id="userResultMap" type="UserAccount">
<constructor>
<idArg column="user_id" javaType="int" name="userId"/>
<arg column="profile" javaType="String" name="profile"/>
<arg column="account_name" javaType="String" name="accountName"/>
</constructor>
</resultMap>
方法2: コンパイル時の-parametersオプションとMyBatis設定
Java 8でコンパイル時に-parametersオプションを指定し、MyBatisの設定でuseActualParamNameを有効にします(デフォルトで有効)。
<settings>
<setting name="useActualParamName" value="true"/>
</settings>
3. 関連オブジェクトのマッピング(association)
使用するエンティティ:
public class Article {
private int articleId;
private String heading;
private String textBody;
protected Writer writer;
}
public class Writer {
protected int writerId;
protected String writerName;
}
ネストされたクエリによる方法
<resultMap id="articleResultMap" type="Article">
<constructor>
<idArg column="article_id" javaType="int" name="articleId"/>
<arg column="heading" javaType="String" name="heading"/>
<arg column="text_body" javaType="String" name="textBody"/>
</constructor>
<association property="writer" column="writer_id" javaType="Writer" select="fetchWriter"/>
</resultMap>
<select id="fetchArticle" resultMap="articleResultMap">
SELECT article_id, heading, text_body, writer_id FROM article WHERE article_id = #{id}
</select>
<select id="fetchWriter" resultType="Writer">
SELECT writer_id, writer_name FROM writer WHERE writer_id = #{id}
</select>
ネストされた結果による方法
<resultMap id="articleResultMap" type="Article">
<constructor>
<idArg column="article_id" javaType="int" name="articleId"/>
<arg column="heading" javaType="String" name="heading"/>
<arg column="text_body" javaType="String" name="textBody"/>
</constructor>
<association property="writer" javaType="Writer">
<id property="writerId" column="writer_id"/>
<result property="writerName" column="writer_name"/>
</association>
</resultMap>
<select id="fetchArticle" resultMap="articleResultMap">
SELECT a.article_id, a.heading, a.text_body, a.writer_id, w.writer_name
FROM article a
LEFT OUTER JOIN writer w ON a.writer_id = w.writer_id
WHERE a.article_id = #{id}
</select>
外部ResultMapを参照する方法
<resultMap id="writerResultMap" type="Writer">
<id property="writerId" column="writer_id"/>
<result property="writerName" column="writer_name"/>
</resultMap>
<resultMap id="articleResultMap" type="Article">
<constructor>
<idArg column="article_id" javaType="int" name="articleId"/>
<arg column="heading" javaType="String" name="heading"/>
<arg column="text_body" javaType="String" name="textBody"/>
</constructor>
<association property="writer" javaType="Writer" resultMap="writerResultMap"/>
</resultMap>
4. コレクションのマッピング(collection)
使用するエンティティ:
public class Article {
private int articleId;
private String heading;
private String textBody;
protected Writer writer;
protected List<Comment> comments;
}
public class Comment {
protected int commentId;
protected String commentText;
protected String detail;
}
ネストされたクエリによる方法
<resultMap id="articleResultMap" type="Article">
<constructor>
<idArg column="article_id" javaType="int" name="articleId"/>
<arg column="heading" javaType="String" name="heading"/>
<arg column="text_body" javaType="String" name="textBody"/>
</constructor>
<association property="writer" javaType="Writer" column="writer_id" select="fetchWriter"/>
<collection property="comments" column="article_id" ofType="Comment" select="fetchComments"/>
</resultMap>
<select id="fetchComments" resultType="Comment">
SELECT * FROM comment WHERE article_id = #{id}
</select>
ネストされた結果による方法
<resultMap id="articleResultMap" type="Article">
<constructor>
<idArg column="article_id" javaType="int" name="articleId"/>
<arg column="heading" javaType="String" name="heading"/>
<arg column="text_body" javaType="String" name="textBody"/>
</constructor>
<association property="writer" javaType="Writer">
<id property="writerId" column="writer_id"/>
<result property="writerName" column="writer_name"/>
</association>
<collection property="comments" ofType="Comment">
<id property="commentId" column="comment_id"/>
<result property="commentText" column="comment_text"/>
<result property="detail" column="detail"/>
</collection>
</resultMap>
<select id="fetchArticle" resultMap="articleResultMap">
SELECT a.article_id, a.heading, a.text_body,
w.writer_id, w.writer_name,
c.comment_id, c.comment_text, c.detail
FROM article a
LEFT OUTER JOIN writer w ON a.writer_id = w.writer_id
LEFT OUTER JOIN comment c ON c.article_id = a.article_id
WHERE a.article_id = #{id}
</select>
5. 識別子を用いたマッピング(discriminator)
使用するエンティティ:
public class Post {
protected int postId;
protected String postTitle;
// getters and setters
}
public class TextPost extends Post {
protected String postContent;
}
public class ImagePost extends Post {
protected String imagePath;
}
簡潔な定義方法
<resultMap id="postResultMap" type="Post">
<id property="postId" column="post_id"/>
<result property="postTitle" column="title"/>
<discriminator javaType="int" column="post_type">
<case value="1" resultType="TextPost">
<result property="postContent" column="content"/>
</case>
<case value="2" resultType="ImagePost">
<result property="imagePath" column="path"/>
</case>
</discriminator>
</resultMap>
外部ResultMapを参照する方法
<resultMap id="textPostResultMap" type="TextPost">
<result property="postContent" column="content"/>
</resultMap>
<resultMap id="imagePostResultMap" type="ImagePost">
<result property="imagePath" column="path"/>
</resultMap>
<resultMap id="postResultMap" type="Post">
<id property="postId" column="post_id"/>
<result property="postTitle" column="title"/>
<discriminator javaType="int" column="post_type">
<case value="1" resultMap="textPostResultMap"/>
<case value="2" resultMap="imagePostResultMap"/>
</discriminator>
</resultMap>