MyBatis resultMap 与 sql
1. 前言
本小节,我们将一起学习 MyBatis resultMap 和 sql。
在前面的小节中,我们了解到 MyBatis 可以自动帮助我们映射数据库数据和 Java 对象,其实这是 MyBatis 在幕后帮我们创建了 resultMap 对象;虽然 MyBatis 可以自动帮助我们做数据映射,但是对于复杂的对象,我们就必须自定义 resultMap 了。
而在书写 SQL 时,势必会有一些 SQL 代码段出现了重复,为了更好的复用它们,MyBatis 提供了 sql 标签。
2. 定义
慕课解释:resultMap 标签用于将数据库数据
映射
为 Java 对象;sql 标签则用来定义可重用
的 SQL 代码段。
3. 实例
4.1 resultMap 实例
4.1.1 xml 实例
在下面这段 select 标签中,SQL 语句返回的是一个复杂对象,即 resultType 上指定的 User。
<select id="selectUserByAgeAndScore" parameterType="com.imooc.mybatis.model.User"
resultType="com.imooc.mybatis.model.User">
SELECT * FROM imooc_user WHERE age = #{age} AND score = #{score}
</select>
在这种情况下,MyBatis 会自动创建 resultMap 对象进行数据的映射,接下来我们直接定义出 resultMap,避免 MyBatis 推断和映射带来的性能损耗。如下:
<resultMap id="userMap" type="com.imooc.mybatis.model.User">
<id property="id" column="id"/>
<result property="username" column="username"/>
<result property="age" column="age"/>
<result property="score" column="score"/>
</resultMap>
<select id="selectUserByAgeAndScore" parameterType="com.imooc.mybatis.model.User"
resultMap="userMap">
SELECT * FROM imooc_user WHERE age = #{age} AND score = #{score}
</select>
我们定义了名为 userMap 的 resultMap 且指定其对应的 Java 类型为 User,在标签的内部,我们还需指定字段之间的映射,除 id 这个特殊的字段外,其它字段均使用 result 标签来映射。
其中 property 是 Java 对象中的字段名称,column 是数据表与之对应的字段名称。
resultMap 定义完毕后,我们在 select 标签中通过 resultMap 属性来设置对应的 id。
TIPS: 注意, resultMap 和 resultType 不能共存,只能二选一。
这样,一次简单的 resultMap 使用就完毕了。
4.1.2 注解实例
通过注解,我们也可以指定 Java 模型对象与数据库字段之间的映射关系,如下:
@Results({
@Result(property = "id", column = "id", id = true),
@Result(property = "username", column = "username"),
@Result(property = "age", column = "age"),
@Result(property = "score", column = "score")
})
@Select("SELECT * FROM imooc_user WHERE id = #{id}")
User selectUserById(Integer id);
Results 注解与 resultMap 对象,包含多个 Result 注解,每个 Result 注解对应了一个字段映射关系。
提示: Results 注解以及 ResultMap 注解虽然存在,但是很少在实际的开发中使用,只需了解即可。
4.2 SQL 实例
我们将目光放到 selectUserByAgeAndScore 语句的内部,在实际的开发中像SELECT * FROM imooc_user
这样的代码段其实非常常见,会在多个 select 标签中用到它。我们可以将其定义为一个 sql 标签,这样所有的 select 标签都可以快速复用到这段代码。
<sql id="selectUser">
SELECT * FROM imooc_user
</sql>
同样的,我们必须为这个代码段定义一个唯一的 id,定义好后,我们就可以在其它标签中使用了:
<select id="selectUserByAgeAndScore" parameterType="com.imooc.mybatis.model.User"
resultMap="userMap">
<include refid="selectUser"/>
WHERE age = #{age} AND score = #{score}
</select>
这里,我们必须使用一个 include 标签来将 SQL 标签包含进来,并且 refid 属性必须是该 SQL 标签的 id 值。这样这段代码仍然可以正常工作。
SQL 标签没有对应注解,只能
在 xml 中使用。
5. 实践
接下来,我们一起来实操巩固一下。
5.1 例1. 查询用户姓名和年龄
请使用 MyBatis 完成在 imooc_user 表中查询用户简略信息的功能。
分析:
很多应用都会有查询用户简略信息这样一个需求,比如我们只需获取用户名和年龄,运用本小节的知识我们可以这样实现它。
先在对应 UserMapper.xml 文件中添加查询用户简略信息的 select 标签,然后在 UserMapper.java 中增加上对应的方法即可。
步骤:
首先,我们新建一个用户简略信息的模型 UserShortCut.java:
package com.imooc.mybatis.model;
public class UserShortCut {
private String username;
private Integer age;
// 省略了重要的 getter 和 setter 方法
}
并在 UserMapper.xml 添加上 resultMap 、sql 和 select 标签:
<!-- 复用的 sql 代码段 -->
<sql id="selectUserShortcutMap">
SELECT username,age FROM imooc_user
</sql>
<!-- 结果映射集 -->
<resultMap id="userShortcutMap" type="com.imooc.mybatis.model.UserShortCut">
<result property="username" column="username"/>
<result property="age" column="age"/>
</resultMap>
<!-- 查询语句 -->
<select id="selectUserShortcutById" resultMap="userShortcutMap">
<include refid="selectUserShortcutMap"/>
WHERE id = #{id}
</select>
接下来,给 UserMapper.java 接口添加上对应的方法,以便在程序中调用。
package com.imooc.mybatis.mapper;
import com.imooc.mybatis.model.UserShortCut;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface UserMapper {
UserShortCut selectUserShortcutById(Integer id);
}
结果:
通过如下代码,我们运行 selectUserShortcutById 方法。
UserMapper userMapper = session.getMapper(UserMapper.class);
UserShortCut shortCut = userMapper.selectUserShortcutById(1);
System.out.println(shortCut);
结果如下:
UserShortCut{username='peter', age=18}
6. 小结
- SQL 是一个非常好用的标签,能够减少大量重复的 SQL 代码书写,但是也降低 SQL 的可读性。
- MyBatis 会自动生成 resultMap,这会为我们节省了大量的时间,如果不是对性能十分严苛,那么 resultType 是够用的。