3.Mapper(對映器)
一、簡介
對映器是 MyBatis 中最重要的檔案,檔案中包含一組 SQL 語句(例如查詢、新增、刪除、修改),這些語句稱為對映語句或對映 SQL 語句。
對映器由 Java 介面和 XML 檔案(或註解)共同組成,它的作用如下。
- 定義引數型別
- 配置快取
- 提供 SQL 語句和動態 SQL
- 定義查詢結果和 POJO 的對映關係
對映器有以下兩種實現方式。
- 通過 XML 檔案方式實現,比如我們在 mybatis-config.xml 檔案中描述的 XML 檔案,用來生成 mapper。
- 通過註解的方式實現,使用 Configuration 物件註冊 Mapper 介面。
如果 SQL 語句存在動態 SQL 或者比較複雜,使用註解寫在 Java 檔案裡可讀性差,且增加了維護的成本。所以一般建議使用 XML 檔案配置的方式,避免重複編寫 SQL 語句。
二、XML實現對映器
XML 定義對映器分為兩個部分:介面和XML。下面先定義介面 WebsiteMapper。
package net.biancheng.mapper;
import java.util.List;
import net.biancheng.po.Website;
public interface WebsiteMapper {
public List<Website> selectAllWebsite();
}
WebsiteMapper.xml 程式碼如下。
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="net.biancheng.mapper.WebsiteMapper"> <!-- 查詢所有網站資訊 --> <select id="selectAllWebsite" resultType="net.biancheng.po.Website"> select * from website </select> </mapper>
下面對上述 XML 檔案進行講解。
- namespace 用來定義名稱空間,該名稱空間和定義介面的全限定名一致。
- <select> 元素表明這是一條查詢語句,屬性 id 用來標識這條 SQL。resultType 表示返回的是一個 Website 型別的值。
在 MyBatis 配置檔案中新增以下程式碼。
- <mapper resource="net/biancheng/mapper/WebsiteMapper.xml" />
該語句用來引入 XML 檔案,MyBatis 會讀取WebsiteMapper.xml 檔案,生成對映器。
下面進行測試,用 SqlSession 來獲取 Mapper,Test 類程式碼如下。
public class Test {
public static void main(String[] args) throws IOException {
InputStream config = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory ssf = new SqlSessionFactoryBuilder().build(config);
SqlSession ss = ssf.openSession();
WebsiteMapper websiteMapper = ss.getMapper(WebsiteMapper.class);
List<Website> websitelist = websiteMapper.selectAllWebsite();
for (Website site : websitelist) {
System.out.println(site);
}
ss.commit();
ss.close();
}
}
執行結果如下。
DEBUG [main] - ==> Preparing: select * from website
DEBUG [main] - ==> Parameters:
DEBUG [main] - <== Total: 1
Website[id=1,name=程式設計幫,url=https://www.biancheng.net/,age=21,country=CN,createtime=Tue Feb 23 10:20:40 CST 2021]
三、註解實現對映器
使用註解的方式實現對映器,只需要在介面中使用 Java 註解,注入 SQL 即可。如下所示。
package net.biancheng.mapper;
import java.util.List;
import org.apache.ibatis.annotations.Select;
import net.biancheng.po.Website;
public interface WebsiteMapper2 {
@Select(value = "select * from website")
public List<Website> selectAllWebsite();
}
這裡我們使用了 @Select 註解,並且注入了和 XML 中相同的 select 語句。
如果使用註解和 XML 檔案兩種方式同時定義,那麼 XML 方式將覆蓋掉註解方式。
雖然這裡註解的方式看起來比 XML 簡單,但是現實中我們遇到的 SQL 會比該例子複雜得多。如果 SQL 語句中有多個表的關聯、多個查詢條件、級聯、條件分支等,顯然這條 SQL 就會複雜的多,所以並不建議讀者使用這種方式。比如下面這條 SQL。
select * from t_user u
left join t_user_role ur on u.id = ur.user_id
left join t_role r on ur.role_id = r.id
left join t_user_info ui on u.id = ui.user_id
left join t_female_health fh on u.id = fh.user_id
left join t_male_health mh on u.id = mh.user_id
where u.user_name like concat('%', ${userName},'%')
and r.role_name like concat('%', ${roleName},'%')
and u.sex = 1
and ui.head_image is not null;
如果把以上 SQL 放到 @Select 註解中,無疑會大大降低程式碼的可讀性。如果同時還要考慮使用動態 SQL 或需要加入其他的邏輯,這樣就使得這個註解更加複雜了,不利於日後的維護和修改。
此外,XML 可以相互引入,而註解是不可以的,所以在一些比較複雜的場景下,使用 XML 方式會更加靈活和方便。因此大部分的企業都以 XML 為主,本教程也會保持一致,以 XML 方式來建立對映器。當然在一些簡單的表和應用中使用註解方式也會比較簡單。
這個介面可以在 XML 中定義,將在 mybatis-config.xml 中配置 XML 的語句修改為以下語句即可。
- <mapper resource="com/mybatis/mapper/WebsiteMapper2" />
也可以使用 configuration 物件註冊這個介面,比如:
- configuration.addMapper(WebsiteMapper2.class);
四、MyBatis 對映器的主要元素
下面介紹在對映器中可以定義哪些元素,以及它們的作用。
元素名稱 | 描述 | 備註 |
---|---|---|
mapper | 對映檔案的根節點,只有 namescape 一個屬性 | namescape 作用如下:
|
select | 查詢語句,最常用、最複雜的元素之一 | 可以自定義引數,返回結果集等 |
insert | 插入語句 | 執行後返回一個整數,代表插入的條數 |
update | 更新語句 | 執行後返回一個整數,代表更新的條數 |
delete | 刪除語句 | 執行後返回一個整數,代表刪除的條數 |
parameterMap | 定義引數對映關係 | 即將被刪除的元素,不建議使用 |
sql | 允許定義一部分的 SQL,然後在各個地方引用它 | 例如,一張表列名,我們可以一次定義,在多個 SQL 語句中使用 |
resultMap | 用來描述資料庫結果集與物件的對應關係,它是最複雜、最強大的元素 | 提供對映規則 |
cache | 配置給定名稱空間的快取 | - |
cache-ref | 其它名稱空間快取配置的引用 | - |
後面文章中會詳細介紹以上元素。
五、拓展
關於 MyBatis 的 SQL 對映檔案中的 mapper 元素的 namescape 屬性有如下要求。
- namescape 的命名必須跟某個 DAO 介面同名,同屬於 DAO 層,因此程式碼結構上,對映檔案與該介面應放置在同一 package 下(如 net.biancheng.dao.website),並且習慣上是以 Mapper 結尾(如 WebsiteMapper.java、WebsiteMapper.xml)。
- 不同的 mapper 檔案中子元素的 id 可以相同,MyBatis 通過 namescape 和子元素的 id 聯合區分。介面中的方法與對映檔案中的 SQL 語句 id 應一 一對應。