1. 程式人生 > 其它 >3.Mapper(對映器)

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 作用如下:
  • 用於區分不同的 mapper,全域性唯一
  • 繫結DAO介面,即面向介面程式設計。當 namescape 繫結某一介面後,可以不用寫該介面的實現類,MyBatis 會通過介面的完整限定名查詢到對應的 mapper 配置來執行 SQL 語句。因此 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 應一 一對應。