MyBatis 的 resultMap
是一种高级映射策略,用于处理复杂的SQL查询结果和Java对象之间的映射关系。resultMap
提供了比 auto-mapping
更为灵活的映射方式,它允许开发者显式指定数据库列和Java对象属性之间的映射关系,甚至可以处理复杂的数据结构,如关联(一对一、一对多)和集合。
resultMap 基本用法
在 MyBatis 的映射文件中,可以通过 <resultMap>
标签定义一个 resultMap
。<resultMap>
标签有一个 id
属性,用于标识这个 resultMap
的唯一标识符,这样在 <select>
、<insert>
、<update>
或 <delete>
等操作中就可以引用这个 resultMap
。
xml
<resultMap id="userResultMap" type="User">
<id column="id" property="id" />
<result column="user_name" property="userName" />
<result column="email" property="email" />
</resultMap>
在上面的示例中,resultMap
定义了一个映射,将数据库中的 id
、user_name
、email
列映射到 Java 对象 User
的 id
、userName
、email
属性上。
处理复杂映射
resultMap
不仅可以处理简单的列到属性的映射,还可以处理一对一、一对多的关联关系。
- 一对一映射 (使用
<association>
标签)
xml
<resultMap id="userDetailResultMap" type="UserDetail">
<id column="id" property="id" />
<result column="username" property="username" />
<association property="address" javaType="Address">
<id column="address_id" property="id"/>
<result column="street" property="street"/>
<result column="city" property="city"/>
</association>
</resultMap>
- 一对多映射 (使用
<collection>
标签)
xml
<resultMap id="userOrdersResultMap" type="User">
<id column="id" property="id" />
<result column="username" property="username" />
<collection property="orders" ofType="Order">
<id column="order_id" property="id"/>
<result column="order_date" property="orderDate"/>
<result column="amount" property="amount"/>
</collection>
</resultMap>
深入源码解析
在 MyBatis 初始化过程中,它会解析映射文件中的 <resultMap>
标签,创建 ResultMap
对象并存储在 Configuration
对象的 resultMaps
集合中。ResultMap
对象中包含了映射的详细信息,如映射的类型、属性名、列名等。
当执行查询操作并需要映射结果集到Java对象时,MyBatis 将利用这些 ResultMap
对象来进行映射处理。
DefaultResultSetHandler
DefaultResultSetHandler
是 MyBatis 中处理结果集映射的核心类,它的 handleResultSets
方法负责将 JDBC 的 ResultSet
转换成Java对象。
java
private List<Object> handleResultSet(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds) throws SQLException {
final DefaultResultContext<Object> resultContext = new DefaultResultContext<>();
skipRows(rsw.getResultSet(), rowBounds);
while (resultContext.getResultCount() < rowBounds.getLimit() && rsw.getResultSet().next()) {
final ResultMap discriminatedResultMap = resolveDiscriminatedResultMap(rsw.getResultSet(), resultMap, null);
final Object rowValue = getRowValue(rsw, discriminatedResultMap, null);
storeObject(resultHandler, resultContext, rowValue, null, rsw.getResultSet());
}
return resultContext.getResultList();
}
在 getRowValue
方法中,MyBatis 会根据 ResultMap
中定义的映射关系,从 ResultSet
中读取数据,并通过反射填充到目标对象的相应属性。
总结
通过 resultMap
,MyBatis 提供了一种强大而灵活的方式来处理从数据库查询结果到Java对象的映射。resultMap
支持复杂的映射场景,如自定义映射、一对一、一对多关联,以及嵌套结果