MyBatis resultMap 與 sql
1. 前言
本小節(jié),我們將一起學(xué)習(xí) MyBatis resultMap 和 sql。
在前面的小節(jié)中,我們了解到 MyBatis 可以自動(dòng)幫助我們映射數(shù)據(jù)庫(kù)數(shù)據(jù)和 Java 對(duì)象,其實(shí)這是 MyBatis 在幕后幫我們創(chuàng)建了 resultMap 對(duì)象;雖然 MyBatis 可以自動(dòng)幫助我們做數(shù)據(jù)映射,但是對(duì)于復(fù)雜的對(duì)象,我們就必須自定義 resultMap 了。
而在書(shū)寫(xiě) SQL 時(shí),勢(shì)必會(huì)有一些 SQL 代碼段出現(xiàn)了重復(fù),為了更好的復(fù)用它們,MyBatis 提供了 sql 標(biāo)簽。
2. 定義
慕課解釋?zhuān)簉esultMap 標(biāo)簽用于將數(shù)據(jù)庫(kù)數(shù)據(jù)
映射
為 Java 對(duì)象;sql 標(biāo)簽則用來(lái)定義可重用
的 SQL 代碼段。
3. 實(shí)例
4.1 resultMap 實(shí)例
4.1.1 xml 實(shí)例
在下面這段 select 標(biāo)簽中,SQL 語(yǔ)句返回的是一個(gè)復(fù)雜對(duì)象,即 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 會(huì)自動(dòng)創(chuàng)建 resultMap 對(duì)象進(jìn)行數(shù)據(jù)的映射,接下來(lái)我們直接定義出 resultMap,避免 MyBatis 推斷和映射帶來(lái)的性能損耗。如下:
<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 且指定其對(duì)應(yīng)的 Java 類(lèi)型為 User,在標(biāo)簽的內(nèi)部,我們還需指定字段之間的映射,除 id 這個(gè)特殊的字段外,其它字段均使用 result 標(biāo)簽來(lái)映射。
其中 property 是 Java 對(duì)象中的字段名稱(chēng),column 是數(shù)據(jù)表與之對(duì)應(yīng)的字段名稱(chēng)。
resultMap 定義完畢后,我們?cè)?select 標(biāo)簽中通過(guò) resultMap 屬性來(lái)設(shè)置對(duì)應(yīng)的 id。
TIPS: 注意, resultMap 和 resultType 不能共存,只能二選一。
這樣,一次簡(jiǎn)單的 resultMap 使用就完畢了。
4.1.2 注解實(shí)例
通過(guò)注解,我們也可以指定 Java 模型對(duì)象與數(shù)據(jù)庫(kù)字段之間的映射關(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 對(duì)象,包含多個(gè) Result 注解,每個(gè) Result 注解對(duì)應(yīng)了一個(gè)字段映射關(guān)系。
提示: Results 注解以及 ResultMap 注解雖然存在,但是很少在實(shí)際的開(kāi)發(fā)中使用,只需了解即可。
4.2 SQL 實(shí)例
我們將目光放到 selectUserByAgeAndScore 語(yǔ)句的內(nèi)部,在實(shí)際的開(kāi)發(fā)中像SELECT * FROM imooc_user
這樣的代碼段其實(shí)非常常見(jiàn),會(huì)在多個(gè) select 標(biāo)簽中用到它。我們可以將其定義為一個(gè) sql 標(biāo)簽,這樣所有的 select 標(biāo)簽都可以快速?gòu)?fù)用到這段代碼。
<sql id="selectUser">
SELECT * FROM imooc_user
</sql>
同樣的,我們必須為這個(gè)代碼段定義一個(gè)唯一的 id,定義好后,我們就可以在其它標(biāo)簽中使用了:
<select id="selectUserByAgeAndScore" parameterType="com.imooc.mybatis.model.User"
resultMap="userMap">
<include refid="selectUser"/>
WHERE age = #{age} AND score = #{score}
</select>
這里,我們必須使用一個(gè) include 標(biāo)簽來(lái)將 SQL 標(biāo)簽包含進(jìn)來(lái),并且 refid 屬性必須是該 SQL 標(biāo)簽的 id 值。這樣這段代碼仍然可以正常工作。
SQL 標(biāo)簽沒(méi)有對(duì)應(yīng)注解,只能
在 xml 中使用。
5. 實(shí)踐
接下來(lái),我們一起來(lái)實(shí)操鞏固一下。
5.1 例1. 查詢(xún)用戶(hù)姓名和年齡
請(qǐng)使用 MyBatis 完成在 imooc_user 表中查詢(xún)用戶(hù)簡(jiǎn)略信息的功能。
分析:
很多應(yīng)用都會(huì)有查詢(xún)用戶(hù)簡(jiǎn)略信息這樣一個(gè)需求,比如我們只需獲取用戶(hù)名和年齡,運(yùn)用本小節(jié)的知識(shí)我們可以這樣實(shí)現(xiàn)它。
先在對(duì)應(yīng) UserMapper.xml 文件中添加查詢(xún)用戶(hù)簡(jiǎn)略信息的 select 標(biāo)簽,然后在 UserMapper.java 中增加上對(duì)應(yīng)的方法即可。
步驟:
首先,我們新建一個(gè)用戶(hù)簡(jiǎn)略信息的模型 UserShortCut.java:
package com.imooc.mybatis.model;
public class UserShortCut {
private String username;
private Integer age;
// 省略了重要的 getter 和 setter 方法
}
并在 UserMapper.xml 添加上 resultMap 、sql 和 select 標(biāo)簽:
<!-- 復(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>
<!-- 查詢(xún)語(yǔ)句 -->
<select id="selectUserShortcutById" resultMap="userShortcutMap">
<include refid="selectUserShortcutMap"/>
WHERE id = #{id}
</select>
接下來(lái),給 UserMapper.java 接口添加上對(duì)應(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é)果:
通過(guò)如下代碼,我們運(yùn)行 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 是一個(gè)非常好用的標(biāo)簽,能夠減少大量重復(fù)的 SQL 代碼書(shū)寫(xiě),但是也降低 SQL 的可讀性。
- MyBatis 會(huì)自動(dòng)生成 resultMap,這會(huì)為我們節(jié)省了大量的時(shí)間,如果不是對(duì)性能十分嚴(yán)苛,那么 resultType 是夠用的。