MyBatis 查詢映射支持 resultType(簡單自動映射)和 resultMap(精確控制)。resultMap 是最強大的映射特性,解決:
<resultMap id="userResultMap" type="com.example.model.User">
<id property="id" column="user_id" jdbcType="BIGINT"/>
<result property="userName" column="user_name" jdbcType="VARCHAR"/>
<result property="email" column="email" jdbcType="VARCHAR"/>
<result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
</resultMap>
<select id="selectUser" resultMap="userResultMap">
SELECT user_id, user_name, email, create_time FROM t_user WHERE id = #{id}
</select>
id:標識主鍵,影響 equals/hashCode 與緩存鍵result:普通字段映射column:SQL 列名/別名property:Java 屬性名jdbcType:可選,針對 NULL 值處理優化使用 resultType 時,MyBatis 內部自動創建 ResultMap,規則:
mapUnderscoreToCamelCase=true → 下劃線自動轉駝峰何時必須用 resultMap:列名屬性名差異大、關聯對象、構造器注入、一對多集合、分步查詢。
<association>public class Blog {
private Long id;
private String title;
private Author author; // 關聯對象
}
public class Author {
private Long id;
private String name;
private String email;
}
<resultMap id="blogDetailMap" type="Blog">
<id property="id" column="blog_id"/>
<result property="title" column="blog_title"/>
<association property="author" javaType="Author">
<id property="id" column="author_id"/>
<result property="name" column="author_name"/>
<result property="email" column="author_email"/>
</association>
</resultMap>
<select id="selectBlogWithAuthor" resultMap="blogDetailMap">
SELECT b.id blog_id, b.title blog_title,
a.id author_id, a.name author_name, a.email author_email
FROM t_blog b LEFT JOIN t_author a ON b.author_id = a.id
WHERE b.id = #{id}
</select>
<resultMap id="blogLazyMap" type="Blog">
<id property="id" column="blog_id"/>
<result property="title" column="blog_title"/>
<association property="author"
select="selectAuthorById"
column="author_id"
fetchType="lazy"/> <!-- lazy/eager -->
</resultMap>
<select id="selectBlog" resultMap="blogLazyMap">
SELECT id blog_id, title blog_title, author_id FROM t_blog WHERE id = #{id}
</select>
<select id="selectAuthorById" resultType="Author">
SELECT id, name, email FROM t_author WHERE id = #{id}
</select>
select:關聯查詢語句 IDcolumn:主查詢列作為參數傳給關聯查詢fetchType:覆蓋全局 lazyLoadingEnabled 設置<collection>public class Blog {
private Long id;
private String title;
private List comments; // 集合屬性
}
public class Comment {
private Long id;
private String content;
private Date createTime;
private Blog blog; // 反向引用
}
<resultMap id="blogWithCommentsMap" type="Blog">
<id property="id" column="blog_id"/> <!-- 關鍵:主鍵去重 -->
<result property="title" column="blog_title"/>
<collection property="comments" ofType="Comment">
<id property="id" column="comment_id"/>
<result property="content" column="comment_content"/>
<result property="createTime" column="comment_time"/>
</collection>
</resultMap>
<select id="selectBlogWithComments" resultMap="blogWithCommentsMap">
SELECT b.id blog_id, b.title blog_title,
c.id comment_id, c.content comment_content, c.create_time comment_time
FROM t_blog b LEFT JOIN t_comment c ON b.id = c.blog_id
WHERE b.id = #{id}
</select>
ofType:集合泛型類型(非 javaType)<id> 必不可少:MyBatis 憑此去重,否則一條 Blog 會重複 N 次<resultMap id="blogCommentsLazyMap" type="Blog">
<id property="id" column="id"/>
<result property="title" column="title"/>
<collection property="comments"
select="selectCommentsByBlogId"
column="id"
fetchType="lazy"/>
</resultMap>
<select id="selectBlog" resultMap="blogCommentsLazyMap">
SELECT id, title FROM t_blog WHERE id = #{id}
</select>
<select id="selectCommentsByBlogId" resultType="Comment">
SELECT id, content, create_time FROM t_comment WHERE blog_id = #{id}
</select>
Comment 中引用 Blog,Blog 中引用 Comment 列表。MyBatis 通過 resultMap 互相引用自動處理:
<resultMap id="commentMap" type="Comment">
<id property="id" column="comment_id"/>
<result property="content" column="comment_content"/>
<association property="blog" resultMap="blogSimpleMap"/> <!-- 引用簡化 Blog 映射 -->
</resultMap>
<resultMap id="blogSimpleMap" type="Blog">
<id property="id" column="blog_id"/>
<result property="title" column="blog_title"/>
<!-- 不包含 comments,避免無限遞歸 -->
</resultMap>
根據字段值動態選擇 resultMap(如不同類型用戶映射到不同子類):
<resultMap id="vehicleMap" type="Vehicle">
<id property="id" column="id"/>
<result property="brand" column="brand"/>
<discriminator javaType="String" column="vehicle_type">
<case value="CAR" resultMap="carMap"/>
<case value="TRUCK" resultMap="truckMap"/>
</discriminator>
</resultMap>
<resultMap id="carMap" type="Car" extends="vehicleMap">
<result property="seatCount" column="seat_count"/>
</resultMap>
<resultMap id="userMap" type="User">
<constructor>
<idArg column="id" javaType="Long" name="id"/>
<arg column="user_name" javaType="String" name="userName"/>
<arg column="email" javaType="String" name="email"/>
</constructor>
</resultMap>
-- 對應構造器
public User(Long id, String userName, String email) { ... }
<id> 去重,否則主對象重複fetchType="lazy" 按需加載resultMap 是 MyBatis 映射核心,掌握 <id/result> 基礎映射、<association> 一對一、<collection> 一對多、discriminator 多態、constructor 構造器注入、嵌套結果 vs 分步查詢權衡,能應對 99% 的 ORM 映射場景。原則:簡單自動、複雜精確、關聯去重、按需加載、避免循環。