在 MyBatis 框架中,mapper.xml
文件里的 SQL 语句在以下几种常见场景下需要用到 resultMap
:
1. 结果集字段与实体类属性名称不匹配
当 SQL 查询结果集中的列名和要映射的 Java 实体类的属性名不一致时,需要 resultMap
来指定映射关系。例如,数据库表中的列名为 user_name
,但 Java 实体类 User
中的属性名为 userName
,此时可以通过 resultMap
来建立正确的映射,此种情况也可以在配置文件中开启驼峰映射解决,示例如下:
xml
bash
<resultMap id="userResultMap" type="com.example.domain.User">
<result property="userName" column="user_name"/>
</resultMap>
<select id="getUserById" resultMap="userResultMap">
SELECT user_name FROM users WHERE id = #{id}
</select>
通过 resultMap
的 property
指定实体类属性,column
指定查询结果集中的列名,从而让 MyBatis 能够正确地将查询结果赋值给实体类的属性。
2. 处理复杂的嵌套结果(一对一、一对多关系)
- 一对一关系 :当查询结果涉及到关联表的一对一关系,且需要将关联数据映射到一个包含子对象的实体类中时,可使用
resultMap
进行嵌套结果映射。比如,查询用户及其关联的部门信息,User
实体类中有一个Department
类型的属性。
xml
xml
<resultMap id="userWithDeptResultMap" type="com.example.domain.User">
<id property="id" column="user_id"/>
<result property="userName" column="user_name"/>
<!-- 嵌套结果映射处理一对一关系 -->
<association property="department" javaType="com.example.domain.Department">
<id property="id" column="dept_id"/>
<result property="deptName" column="dept_name"/>
</association>
</resultMap>
<select id="getUserWithDeptById" resultMap="userWithDeptResultMap">
SELECT
u.user_id, u.user_name, d.dept_id, d.dept_name
FROM
users u
LEFT JOIN
departments d ON u.dept_id = d.dept_id
WHERE
u.user_id = #{id}
</select>
- 一对多关系 :如果查询结果涉及到一对多的关系,比如查询部门及其包含的所有用户,
Department
实体类中有一个List<User>
类型的属性来存储该部门的用户列表。
xml
xml
<resultMap id="deptWithUsersResultMap" type="com.example.domain.Department">
<id property="id" column="dept_id"/>
<result property="deptName" column="dept_name"/>
<!-- 嵌套结果映射处理一对多关系 -->
<collection property="userList" ofType="com.example.domain.User">
<id property="id" column="user_id"/>
<result property="userName" column="user_name"/>
</collection>
</resultMap>
<select id="getDeptWithUsersById" resultMap="deptWithUsersResultMap">
SELECT
d.dept_id, d.dept_name, u.user_id, u.user_name
FROM
departments d
LEFT JOIN
users u ON d.dept_id = u.dept_id
WHERE
d.dept_id = #{id}
</select>
3. 复用映射规则
当多个 SQL 查询需要使用相同的结果映射逻辑时,可以定义一个 resultMap
并在多个 select
标签中复用,这样可以提高代码的复用性和可维护性。例如,有多个查询都需要将用户信息映射到 User
实体类,且映射规则一致,就可以将映射规则定义在一个 resultMap
中,然后在不同的 select
语句中通过 resultMap
属性引用。
xml
sql
<resultMap id="commonUserResultMap" type="com.example.domain.User">
<id property="id" column="user_id"/>
<result property="userName" column="user_name"/>
<result property="email" column="user_email"/>
</resultMap>
<select id="getUserById" resultMap="commonUserResultMap">
SELECT user_id, user_name, user_email FROM users WHERE id = #{id}
</select>
<select id="getAllUsers" resultMap="commonUserResultMap">
SELECT user_id, user_name, user_email FROM users
</select>
4. 对查询结果进行类型转换或特殊处理
如果查询结果集中某个字段的数据类型需要转换为与实体类属性不同的类型,或者需要对结果进行一些特殊处理(比如日期格式化等),可以在 resultMap
中通过自定义的 typeHandler
来实现。例如,数据库中存储的日期是时间戳格式,而实体类中对应的属性是 java.util.Date
类型,就可以配置 typeHandler
进行转换。
xml
ini
<resultMap id="userWithDateResultMap" type="com.example.domain.User">
<id property="id" column="user_id"/>
<result property="userName" column="user_name"/>
<result property="createTime" column="create_time" typeHandler="com.example.handler.TimestampToDateTypeHandler"/>
</resultMap>
<select id="getUserWithCreateTime" resultMap="userWithDateResultMap">
SELECT user_id, user_name, create_time FROM users WHERE id = #{id}
</select>
总之,resultMap
提供了一种灵活强大的方式来控制 SQL 查询结果到 Java 实体类的映射过程,在面对复杂映射需求时能发挥重要作用。