MyBatis 映射檔寫法多樣,不同策略對開發效率、維護成本影響巨大。本文以 User 實體類與 UserMap.xml 為例,示範一種結構清晰、支援多表關聯、減少重複代碼的進階映射寫法。
User 類包含大量引用型別屬性(Office company、Dept dept、Role role、School school 等),而非單純基本型別。這要求映射檔能將多表 JOIN 查詢結果自動填充至巢狀物件圖中,例如 user.getCompany().getId() 直接可用。
<sql id="userColumns">
a.id,
a.company_id AS "company.id",
a.office_id AS "office.id",
a.login_name, a.password, a.no, a.name, ...,
c.name AS "company.name",
c.parent_id AS "company.parent.id",
ca.id AS "company.area.id",
o.name AS "office.name",
sc.xxlx AS "school.xxlx",
sc.xxmc AS "school.xxmc"
</sql>
<sql id="userJoins">
LEFT JOIN sys_office c ON c.id = a.company_id
LEFT JOIN sys_area ca ON ca.id = c.area_id
LEFT JOIN sys_office o ON o.id = a.office_id
LEFT JOIN sys_area oa ON oa.id = o.area_id
LEFT JOIN xj_school sc ON sc.id = a.school
</sql>
關鍵點:使用 AS "property.nestedProperty" 別名語法,MyBatis 會自動根據點號路徑建立巢狀物件並注入值,無需手寫 <resultMap>。
<select id="getUserById" resultType="User">
SELECT <include refid="userColumns"/>
FROM sys_user a
<include refid="userJoins"/>
WHERE a.id = #{id}
</select>
<select id="getByLoginName" resultType="User" parameterType="User">
SELECT <include refid="userColumns"/>
FROM sys_user a
<include refid="userJoins"/>
WHERE a.login_name = #{loginName} AND a.del_flag = #{DEL_FLAG_NORMAL}
</select>
直接指定 resultType="User",MyBatis 依別名自動映射至巢狀物件,省去冗長 resultMap 定義。
<insert id="insert">
INSERT INTO sys_user(..., company_id, office_id, ..., create_by, update_by, school)
VALUES (#{id}, #{company.id}, #{office.id}, ..., #{createBy.id}, #{updateBy.id}, #{school.id})
</insert>
<update id="update">
UPDATE sys_user SET
company_id = #{company.id},
office_id = #{office.id},
update_by = #{updateBy.id},
school = #{school.id}
WHERE id = #{id}
</update>
插入/更新時,OGNL 表達式 #{company.id} 會自動取巢狀物件屬性值,實現雙向無縫映射。
userJoins 片段,業務邏輯不感知表結構此模式最適合「主表 + 多維度關聯表」的典型業務查詢(如用戶/訂單/商品詳情)。注意:
private Office company = new Office();)避免 NPE