MyBatis resultMap 與 sql
1. 前言
本小節(jié),我們將一起學習 MyBatis resultMap 和 sql。
在前面的小節(jié)中,我們了解到 MyBatis 可以自動幫助我們映射數(shù)據(jù)庫數(shù)據(jù)和 Java 對象,其實這是 MyBatis 在幕后幫我們創(chuàng)建了 resultMap 對象;雖然 MyBatis 可以自動幫助我們做數(shù)據(jù)映射,但是對于復(fù)雜的對象,我們就必須自定義 resultMap 了。
而在書寫 SQL 時,勢必會有一些 SQL 代碼段出現(xiàn)了重復(fù),為了更好的復(fù)用它們,MyBatis 提供了 sql 標簽。
2. 定義
慕課解釋:resultMap 標簽用于將數(shù)據(jù)庫數(shù)據(jù)
映射
為 Java 對象;sql 標簽則用來定義可重用
的 SQL 代碼段。
3. 實例
4.1 resultMap 實例
4.1.1 xml 實例
在下面這段 select 標簽中,SQL 語句返回的是一個復(fù)雜對象,即 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 會自動創(chuàng)建 resultMap 對象進行數(shù)據(jù)的映射,接下來我們直接定義出 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 且指定其對應(yīng)的 Java 類型為 User,在標簽的內(nèi)部,我們還需指定字段之間的映射,除 id 這個特殊的字段外,其它字段均使用 result 標簽來映射。
其中 property 是 Java 對象中的字段名稱,column 是數(shù)據(jù)表與之對應(yīng)的字段名稱。
resultMap 定義完畢后,我們在 select 標簽中通過 resultMap 屬性來設(shè)置對應(yīng)的 id。
TIPS: 注意, resultMap 和 resultType 不能共存,只能二選一。
這樣,一次簡單的 resultMap 使用就完畢了。
4.1.2 注解實例
通過注解,我們也可以指定 Java 模型對象與數(shù)據(jù)庫字段之間的映射關(guān)系,如下:
@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 注解對應(yīng)了一個字段映射關(guān)系。
提示: Results 注解以及 ResultMap 注解雖然存在,但是很少在實際的開發(fā)中使用,只需了解即可。
4.2 SQL 實例
我們將目光放到 selectUserByAgeAndScore 語句的內(nèi)部,在實際的開發(fā)中像SELECT * FROM imooc_user
這樣的代碼段其實非常常見,會在多個 select 標簽中用到它。我們可以將其定義為一個 sql 標簽,這樣所有的 select 標簽都可以快速復(fù)用到這段代碼。
<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 標簽沒有對應(yīng)注解,只能
在 xml 中使用。
5. 實踐
接下來,我們一起來實操鞏固一下。
5.1 例1. 查詢用戶姓名和年齡
請使用 MyBatis 完成在 imooc_user 表中查詢用戶簡略信息的功能。
分析:
很多應(yīng)用都會有查詢用戶簡略信息這樣一個需求,比如我們只需獲取用戶名和年齡,運用本小節(jié)的知識我們可以這樣實現(xiàn)它。
先在對應(yīng) UserMapper.xml 文件中添加查詢用戶簡略信息的 select 標簽,然后在 UserMapper.java 中增加上對應(yīng)的方法即可。
步驟:
首先,我們新建一個用戶簡略信息的模型 UserShortCut.java:
package com.imooc.mybatis.model;
public class UserShortCut {
private String username;
private Integer age;
// 省略了重要的 getter 和 setter 方法
}
并在 UserMapper.xml 添加上 resultMap 、sql 和 select 標簽:
<!-- 復(fù)用的 sql 代碼段 -->
<sql id="selectUserShortcutMap">
SELECT username,age FROM imooc_user
</sql>
<!-- 結(jié)果映射集 -->
<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 接口添加上對應(yīng)的方法,以便在程序中調(diào)用。
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);
}
結(jié)果:
通過如下代碼,我們運行 selectUserShortcutById 方法。
UserMapper userMapper = session.getMapper(UserMapper.class);
UserShortCut shortCut = userMapper.selectUserShortcutById(1);
System.out.println(shortCut);
結(jié)果如下:
UserShortCut{username='peter', age=18}
6. 小結(jié)
- SQL 是一個非常好用的標簽,能夠減少大量重復(fù)的 SQL 代碼書寫,但是也降低 SQL 的可讀性。
- MyBatis 會自動生成 resultMap,這會為我們節(jié)省了大量的時間,如果不是對性能十分嚴苛,那么 resultType 是夠用的。