MyBatis基礎知識掃盲

本文不講具體的MyBatis的一些用法,只記錄一些MyBatis的基礎知識

MyBatis 是什麼

在移動互聯網時代,MyBatis 成爲了目前互聯網 Java 持久框架的首選。

MyBatis 本是 Apache 的一個開源項目——iBatis,2010 年這個項目由 Apache Software Foundation 遷移到了 Google Code,並且改名爲 MyBatis。

MyBatis 是一個基於 Java 的持久層框架。MyBatis 提供的持久層框架包括 SQL Maps 和 Data Access Objects(DAO),它消除了幾乎所有的 JDBC 代碼和參數的手工設置以及結果集的檢索。

MyBatis 使用簡單的 XML 或註解用於配置和原始映射,將接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java 對象)映射成數據庫中的記錄。

目前,Java 的持久層框架產品有許多,常見的有 Hibernate 和 MyBatis。

Hibernate 和 MyBatis 的區別

1)sql 優化方面

  • Hibernate 不需要編寫大量的 SQL,就可以完全映射,提供了日誌、緩存、級聯(級聯比 MyBatis 強大)等特性,此外還提供 HQL(Hibernate Query Language)對 POJO 進行操作。但會多消耗性能。
  • MyBatis 手動編寫 SQL,支持動態 SQL、處理列表、動態生成表名、支持存儲過程。工作量相對大些。

2)開發方面

  • MyBatis 是一個半自動映射的框架,因爲 MyBatis 需要手動匹配 POJO、SQL 和映射關係。
  • Hibernate 是一個全表映射的框架,只需提供 POJO 和映射關係即可。

3)Hibernate 優勢

  • Hibernate 的 DAO 層開發比 MyBatis 簡單,Mybatis 需要維護 SQL 和結果映射。
  • Hibernate 對對象的維護和緩存要比 MyBatis 好,對增刪改查的對象的維護要方便。
  • Hibernate 數據庫移植性很好,MyBatis 的數據庫移植性不好,不同的數據庫需要寫不同 SQL。
  • Hibernate 有更好的二級緩存機制,可以使用第三方緩存。MyBatis 本身提供的緩存機制不佳。

4)Mybatis優勢

  • MyBatis 可以進行更爲細緻的 SQL 優化,可以減少查詢字段。
  • MyBatis 容易掌握,而 Hibernate 門檻較高。

總的來說,MyBatis 是一個小巧、方便、高效、簡單、直接、半自動化的持久層框架,Hibernate 是一個強大、方便、高效、複雜、間接、全自動化的持久層框架。

所以對於性能要求不太苛刻的系統,比如管理系統、ERP 等推薦使用 Hibernate,而對於性能要求高、響應快、靈活的系統則推薦使用 MyBatis。

MyBatis 的工作原理

在學習 MyBatis 程序之前,讀者需要了解一下 MyBatis 工作原理,以便於理解程序。MyBatis 的工作原理如圖所示。

下面對圖中的每步流程進行說明。

1)讀取 MyBatis 配置文件:mybatis-config.xml 爲 MyBatis 的全局配置文件,配置了 MyBatis 的運行環境等信息,例如數據庫連接信息。

2)加載映射文件。映射文件即 SQL 映射文件,該文件中配置了操作數據庫的 SQL 語句,需要在 MyBatis 配置文件 mybatis-config.xml 中加載。mybatis-config.xml 文件可以加載多個映射文件,每個文件對應數據庫中的一張表。

3)構造會話工廠:通過 MyBatis 的環境等配置信息構建會話工廠 SqlSessionFactory。

MyBatis框架的執行流程圖

4)創建會話對象:由會話工廠創建 SqlSession 對象,該對象中包含了執行 SQL 語句的所有方法。

5)Executor 執行器:MyBatis 底層定義了一個 Executor 接口來操作數據庫,它將根據 SqlSession 傳遞的參數動態地生成需要執行的 SQL 語句,同時負責查詢緩存的維護。

6)MappedStatement 對象:在 Executor 接口的執行方法中有一個 MappedStatement 類型的參數,該參數是對映射信息的封裝,用於存儲要映射的 SQL 語句的 id、參數等信息。

7)輸入參數映射:輸入參數類型可以是 Map、List 等集合類型,也可以是基本數據類型和 POJO 類型。輸入參數映射過程類似於 JDBC 對 preparedStatement 對象設置參數的過程。

8)輸出結果映射:輸出結果類型可以是 Map、 List 等集合類型,也可以是基本數據類型和 POJO 類型。輸出結果映射過程類似於 JDBC 對結果集的解析過程。

MyBatis 的核心組件

我們先來看 MyBatis 的“表面現象”——組件,並且討論它們的作用,然後討論它們的實現原理。MyBatis 的核心組件分爲 4 個部分。

1)SqlSessionFactoryBuilder(構造器):它會根據配置或者代碼來生成 SqlSessionFactory,採用的是分步構建的 Builder 模式。

2)SqlSessionFactory(工廠接口):依靠它來生成 SqlSession,使用的是工廠模式。

3)SqlSession(會話):一個既可以發送 SQL 執行返回結果,也可以獲取 Mapper 的接口。在現有的技術中,一般我們會讓其在業務邏輯代碼中“消失”,而使用的是 MyBatis 提供的 SQL Mapper 接口編程技術,它能提高代碼的可讀性和可維護性。

4)SQL Mapper(映射器):MyBatis 新設計存在的組件,它由一個 Java 接口和 XML 文件(或註解)構成,需要給出對應的 SQL 和映射規則。它負責發送 SQL 去執行,並返回結果。

用一張圖來展示 MyBatis 核心組件之間的關係,如圖所示。

MyBatis核心組件

注意,無論是映射器還是 SqlSession 都可以發送 SQL 到數據庫執行

MyBatis SqlSessionFactory

使用 MyBatis 首先是使用配置或者代碼去生產 SqlSessionFactory,而 MyBatis 提供了構造器 SqlSessionFactoryBuilder。

它提供了一個類 org.apache.ibatis.session.Configuration 作爲引導,採用的是 Builder 模式。具體的分步則是在 Configuration 類裏面完成的,當然會有很多內容,包括你很感興趣的插件。

在 MyBatis 中,既可以通過讀取配置的 XML 文件的形式生成 SqlSessionFactory,也可以通過 Java 代碼的形式去生成 SqlSessionFactory。

筆者強烈推薦採用 XML 的形式,因爲代碼的方式在需要修改的時候會比較麻煩。當配置了 XML 或者提供代碼後,MyBatis 會讀取配置文件,通過 Configuration 類對象構建整個 MyBatis 的上下文。

注意,SqlSessionFactory 是一個接口,在 MyBatis 中它存在兩個實現類:SqlSessionManager 和 DefaultSqlSessionFactory。

一般而言,具體是由 DefaultSqlSessionFactory 去實現的,而 SqlSessionManager 使用在多線程的環境中,它的具體實現依靠 DefaultSqlSessionFactory,它們之間的關係如圖所示。

SqlSessionFactory的生成

每個基於 MyBatis 的應用都是以一個 SqlSessionFactory 的實例爲中心的,而 SqlSessionFactory 唯一的作用就是生產 MyBatis 的核心接口對象 SqlSession,所以它的責任是唯一的。我們往往會採用單例模式處理它,下面討論使用配置文件和 Java 代碼兩種形式去生成 SqlSessionFactory 的方法。

使用 XML 構建 SqlSessionFactory

首先,在 MyBatis 中的 XML 分爲兩類,一類是基礎配置文件,通常只有一個,主要是配置一些最基本的上下文參數和運行環境;另一類是映射文件,它可以配置映射關係、SQL、參數等信息。

先看一份簡易的基礎配置文件,我們把它命名爲 mybatis-config.xml,放在工程類路徑下,其內容如下所示。

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <typeAliases><!--別名-->
        <typeAliases alias="user" type="com.mybatis.po.User"/>
    </typeAliases>
    <!-- 數據庫環境 -->
    <environments default="development">
        <environment id="development">
            <!-- 使用JDBC的事務管理 -->
            <transactionManager type="JDBC" />
            <dataSource type="POOLED">
                <!-- MySQL數據庫驅動 -->
                <property name="driver" value="com.mysql.jdbc.Driver" />
                <!-- 連接數據庫的URL -->
                <property name="url"
                    value="jdbc:mysql://localhost:3306/mybatis?characterEncoding=utf8" />
                <property name="username" value="root" />
                <property name="password" value="1128" />
            </dataSource>
        </environment>
    </environments>
    <!-- 將mapper文件加入到配置文件中 -->
    <mappers>
        <mapper resource="com/mybatis/mapper/UserMapper.xml" />
    </mappers>
</configuration>

我們描述一下 MyBatis 的基礎配置文件:

  • < typeAlias > 元素定義了一個別名 user,它代表着 com.mybatis.po.User 這個類。這樣定義後,在 MyBatis 上下文中就可以使用別名去代替全限定名了。
  • < environment> 元素的定義,這裏描述的是數據庫。它裏面的 元素是配置事務管理器,這裏採用的是 MyBatis 的 JDBC 管理器方式。
  • < dataSource> 元素配置數據庫,其中屬性 type=“POOLED” 代表採用 MyBatis 內部提供的連接池方式,最後定義一些關於 JDBC 的屬性信息。
  • < mapper> 元素代表引入的那些映射器,在談到映射器時會詳細討論它。

有了基礎配置文件,就可以用一段很簡短的代碼來生成 SqlSessionFactory 了,如下所示。

SqlSessionFactory factory = null;
String resource = "mybatis-config.xml";
InputStream is;
try {
    InputStream is = Resources.getResourceAsStream(resource);
    factory = new SqlSessionFactoryBuilder().build(is);
} catch (IOException e) {
    e.printStackTrace();
}

首先讀取 mybatis-config.xml,然後通過 SqlSessionFactoryBuilder 的 Builder 方法去創建 SqlSessionFactory。整個過程比較簡單,而裏面的步驟還是比較煩瑣的,只是 MyBatis 採用了 Builder 模式爲開發者隱藏了這些細節。這樣一個 SqlSessionFactory 就被創建出來了。

採用 XML 創建的形式,信息在配置文件中,有利於我們日後的維護和修改,避免了重新編譯代碼,因此筆者推薦這種方式。

使用代碼創建 SqlSessionFactory

雖然筆者不推薦使用這種方式,但是我們還是談談如何使用它。通過代碼來實現與使用 XML 構建 SqlSessionFactory 一樣的功能——創建 SqlSessionFactory,代碼如下所示。

// 數據庫連接池信息
PooledDataSource dataSource = new PooledDataSource();
dataSource.setDriver("com.mysql.jdbc.Driver");
dataSource.setUsername("root");
dataSource.setPassword ("1128");
dataSource.setUrl("jdbc:mysql://localhost:3306/mybatis");
dataSource.setDefeultAutoCommit(false);
// 採用 MyBatis 的 JDBC 事務方式
TransactionFactory transactionFactory = new JdbcTransactionFactory();
Environment environment = new Environment ("development", transactionFactory, dataSource);
// 創建 Configuration 對象
Configuration configuration = new Configuration(environment);
// 註冊一個 MyBatis 上下文別名
configuration.getTypeAliasRegistry().registerAlias("role", Role.class);
// 加入一個映射器
configuration.addMapper(RoleMapper.class);
//使用 SqlSessionFactoryBuilder 構建 SqlSessionFactory
SqlSessionFactory SqlSessionFactory =
new SqlSessionFactoryBuilder().build(configuration);
return SqlSessionFactory;

注意代碼中的註釋,它和 XML 方式實現的功能是一致的,只是方式不太一樣而已。但是代碼冗長,如果發生系統修改,那麼有可能需要重新編譯代碼才能繼續,所以這不是一個很好的方式。

除非有特殊的需要,比如在配置文件中,需要配置加密過的數據庫用戶名和密碼,需要我們在生成 SqlSessionFactory 前解密爲明文的時候,纔會考慮使用這樣的方式。

MyBatis SqlSession簡介

在 MyBatis 中,SqlSession 是其核心接口。在 MyBatis 中有兩個實現類,DefaultSqlSession 和 SqlSessionManager。

DefaultSqlSession 是單線程使用的,而 SqlSessionManager 在多線程環境下使用。SqlSession 的作用類似於一個 JDBC 中的 Connection 對象,代表着一個連接資源的啓用。具體而言,它的作用有 3 個:

  • 獲取 Mapper 接口。
  • 發送 SQL 給數據庫。
  • 控制數據庫事務。

先來掌握它的創建方法,有了 SqlSessionFactory 創建的 SqlSession 就十分簡單了,如下所示。

SqlSession sqlSession = SqlSessionFactory.openSession();

注意,SqlSession 只是一個門面接口,它有很多方法,可以直接發送 SQL。它就好像一家軟件公司的商務人員,是一個門面,而實際幹活的是軟件工程師。在 MyBatis 中,真正幹活的是 Executor,我們會在底層看到它。

SqlSession 控制數據庫事務的方法,如下所示。

//定義 SqlSession
SqlSession sqlSession = null;
try {
    // 打開 SqlSession 會話
    sqlSession = SqlSessionFactory.openSession();
    // some code...
    sqlSession.commit();    // 提交事務
} catch (IOException e) {
    sqlSession.rollback();  // 回滾事務
}finally{
    // 在 finally 語句中確保資源被順利關閉
    if(sqlSession != null){
        sqlSession.close();
    }
}

這裏使用 commit 方法提交事務,或者使用 rollback 方法回滾事務。因爲它代表着一個數據庫的連接資源,使用後要及時關閉它,如果不關閉,那麼數據庫的連接資源就會很快被耗費光,整個系統就會陷入癱瘓狀態,所以用 finally 語句保證其順利關閉。

MyBatis實現映射器的2種方式

映射器是 MyBatis 中最重要、最複雜的組件,它由一個接口和對應的 XML 文件(或註解)組成。它可以配置以下內容:

  • 描述映射規則。
  • 提供 SQL 語句,並可以配置 SQL 參數類型、返回類型、緩存刷新等信息。
  • 配置緩存。
  • 提供動態 SQL。

本節闡述兩種實現映射器的方式,XML 文件形式和註解形式。不過在此之前,先用以下 SQL 語句創建 role 表。

CREATE TABLE `role` (
    `id` bigint(20) NOT NULL,
    `role_name` varchar(20) DEFAULT NULL,
    `note` varchar(20) DEFAULT NULL,
    PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

並且定義一個 POJO,它十分簡單,如下所示。

package com.mybatis.po;
public class Role {
    private Long id;
    private String roleName;
    private String note;
/**setter and getter**/
}

映射器的主要作用就是將 SQL 查詢到的結果映射爲一個 POJO,或者將 POJO 的數據插入到數據庫中,並定義一些關於緩存等的重要內容。

注意,開發只是一個接口,而不是一個實現類。初學者可能會產生一個很大的疑問,那就是接口不是不能運行嗎?

是的,接口不能直接運行。MyBatis 運用了動態代理技術使得接口能運行起來,入門階段只要懂得 MyBatis 會爲這個接口生成一個代理對象,代理對象會去處理相關的邏輯即可。

用 XML 實現映射器

用 XML 定義映射器分爲兩個部分:接口和 XML。先定義一個映射器接口,如下所示。

package com.mybatis.mapper;
import com.mybatis.po.Role;
public interface RoleMapper {
    public Role getRole(Long id);
}

在用 XML 方式創建 SqlSession 的配置文件中有這樣一段代碼:

<mapper resource="com/mybatis/mapper/RoleMapper.xml" />

它的作用就是引入一個 XML 文件。用 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="com.mybatis.mapper.RoleMapper">
    <select id="getRole" parameterType="long" resultType="role">
        SELECT id,role_name as roleName,note FROM role WHERE id =#{id}
    </select>
</mapper>

有了這兩個文件,就完成了一個映射器的定義。XML 文件還算比較簡單,我們稍微講解一下:

< mapper> 元素中的屬性 namespace 所對應的是一個接口的全限定名,於是 MyBatis 上下文就可以通過它找到對應的接口。

< select> 元素表明這是一條查詢語句,而屬性 id 標識了這條 SQL,屬性 parameterType=“long” 說明傳遞給 SQL 的是一個 long 型的參數,而 resultType=“role” 表示返回的是一個 role 類型的返回值。而 role 是之前配置文件 mybatis-config.xml 配置的別名,指代的是 com.mybatis.po.Role。

這條 SQL 中的 #{id} 表示傳遞進去的參數。

注意,我們並沒有配置 SQL 執行後和 role 的對應關係,它是如何映射的呢?

其實這裏採用的是一種被稱爲自動映射的功能,MyBatis 在默認情況下提供自動映射,只要 SQL 返回的列名能和 POJO 對應起來即可。

這裏 SQL 返回的列名 id 和 note 是可以和之前定義的 POJO 的屬性對應起來的,而表裏的列 role_name 通過 SQL 別名的改寫,使其成爲 roleName,也是和 POJO 對應起來的,所以此時 MyBatis 就可以把 SQL 查詢的結果通過自動映射的功能映射成爲一個 POJO。

註解實現映射器

除 XML 方式定義映射器外,還可以採用註解方式定義映射器,它只需要一個接口就可以通過 MyBatis 的註解來注入 SQL,如下所示。

package com.mybatis.mapper;
import org.apache.ibatis.annotations.Select;
import com.mybatis.po.Role;
public interface RoleMapper2 {
    @Select("select id,role_name as roleName,note from t_role where id=#{id}")
    public Role getRole(Long id);
}

這完全等同於 XML 方式創建映射器。也許你會覺得使用註解的方式比 XML 方式要簡單得多。如果它和 XML 方式同時定義時,XML 方式將覆蓋掉註解方式,所以 MyBatis 官方推薦使用的是 XML 方式,因此本教程以 XML 方式爲主討論 MyBatis 的應用。

在工作和學習中,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 放入 Java 代碼中,顯然代碼的可讀性也會下降。

如果同時還要考慮使用動態 SQL,比如當參數 userName 爲空,則不使用 u.user_name like concat(’%’,userName,{userName},'%')作爲查詢條件;當 roleName 爲空,則不使用 r.role_name like concat('%',{roleName},’%’)作爲查詢條件,但是還需要加入其他的邏輯,這樣就使得這個註解更加複雜了,不利於日後的維護和修改。

此外,XML 可以相互引入,而註解是不可以的,所以在一些比較複雜的場景下,使用 XML 方式會更加靈活和方便。所以大部分的企業都是以 XML 爲主,本教程也會保持一致,以 XML 方式來創建映射器。當然在一些簡單的表和應用中使用註解方式也會比較簡單。

這個接口可以在 XML 中定義,我們仿造在 mybatis-config.xml 中配置 XML 語句:

<mapper resource="com/mybatis/mapper/RoleMapper.xml" />

把它修改爲下面的形式即可。

<mapper resource="com/mybatis/mapper/RoleMapper2" />

也可以使用 configuration 對象註冊這個接口,比如:

configuration.addMapper(RoleMapper2.class);

MyBatis執行SQL的兩種方式

本節主要介紹 MyBatis 執行 SQL 語句的兩種方式和它們的區別。

SqlSession 發送 SQL

有了映射器就可以通過 SqlSession 發送 SQL 了。我們以 getRole 這條 SQL 爲例看看如何發送 SQL。

Role role = (Role)sqlSession.select("com.mybatis.mapper.RoleMapper.getRole",1L);

selectOne 方法表示使用查詢並且只返回一個對象,而參數則是一個 String 對象和一個 Object 對象。這裏是一個 long 參數,long 參數是它的主鍵。

String 對象是由一個命名空間加上 SQL id 組合而成的,它完全定位了一條 SQL,這樣 MyBatis 就會找到對應的 SQL。如果在 MyBatis 中只有一個 id 爲 getRole 的 SQL,那麼也可以簡寫爲:

Role role = (Role)sqlSession.selectOne("getRole",1L);

這是 MyBatis 前身 iBatis 所留下的方式。

用 Mapper 接口發送 SQL

SqlSession 還可以獲取 Mapper 接口,通過 Mapper 接口發送 SQL,如下所示。

RoleMapper roleMapper = sqlSession.getMapper(RoleMapper.class); Role role = roleMapper.getRole(1L);

通過 SqlSession 的 getMapper 方法來獲取一個 Mapper 接口,就可以調用它的方法了。因爲 XML 文件或者接口註解定義的 SQL 都可以通過“類的全限定名+方法名”查找,所以 MyBatis 會啓用對應的 SQL 進行運行,並返回結果。

對比兩種發送 SQL 方式

上面分別展示了 MyBatis 存在的兩種發送 SQL 的方式,一種用 SqlSession 直接發送,另外一種通過 SqlSession 獲取 Mapper 接口再發送。筆者建議採用 SqlSession 獲取 Mapper 的方式,理由如下:

使用 Mapper 接口編程可以消除 SqlSession 帶來的功能性代碼,提高可讀性,而 SqlSession 發送 SQL,需要一個 SQL id 去匹配 SQL,比較晦澀難懂。使用 Mapper 接口,類似roleMapper.getRole(1L)則是完全面向對象的語言,更能體現業務的邏輯。

使用 Mapper.getRole(1L)方式,IDE 會提示錯誤和校驗,而使用sqlSession.selectOne(“getRole”,1L)語法,只有在運行中才能知道是否會產生錯誤。

目前使用 Mapper 接口編程已成爲主流,尤其在 Spring 中運用 MyBatis 時,Mapper 接口的使用就更爲簡單,所以本教程使用 Mapper 接口的方式討論 MyBatis。

MyBatis 核心組件的生命週期

我們已經掌握了 MyBatis 組件的創建及其基本應用,但這是遠遠不夠的,還需要討論其生命週期。

生命週期是組件的重要問題,尤其是在多線程的環境中,比如互聯網應用、Socket 請求等,而 MyBatis 也常用於多線程的環境中,錯誤使用會造成嚴重的多線程併發問題,爲了正確編寫 MyBatis 的應用程序,我們需要掌握 MyBatis 組件的生命週期。

所謂生命週期就是每一個對象應該存活的時間,比如一些對象一次用完後就要關閉,使它們被 Java 虛擬機(JVM)銷燬,以避免繼續佔用資源,所以我們會根據每一個組件的作用去確定其生命週期。

SqlSessionFactoryBuilder

SqlSessionFactoryBuilder 的作用在於創建 SqlSessionFactory,創建成功後,SqlSessionFactoryBuilder 就失去了作用,所以它只能存在於創建 SqlSessionFactory 的方法中,而不要讓其長期存在。因此 SqlSessionFactoryBuilder 實例的最佳作用域是方法作用域(也就是局部方法變量)。

SqlSessionFactory

SqlSessionFactory 可以被認爲是一個數據庫連接池,它的作用是創建 SqlSession 接口對象。因爲 MyBatis 的本質就是 Java 對數據庫的操作,所以 SqlSessionFactory 的生命週期存在於整個 MyBatis 的應用之中,所以一旦創建了 SqlSessionFactory,就要長期保存它,直至不再使用 MyBatis 應用,所以可以認爲 SqlSessionFactory 的生命週期就等同於 MyBatis 的應用週期。

由於 SqlSessionFactory 是一個對數據庫的連接池,所以它佔據着數據庫的連接資源。如果創建多個 SqlSessionFactory,那麼就存在多個數據庫連接池,這樣不利於對數據庫資源的控制,也會導致數據庫連接資源被消耗光,出現系統宕機等情況,所以儘量避免發生這樣的情況。

因此在一般的應用中我們往往希望 SqlSessionFactory 作爲一個單例,讓它在應用中被共享。所以說 SqlSessionFactory 的最佳作用域是應用作用域。

SqlSession

如果說 SqlSessionFactory 相當於數據庫連接池,那麼 SqlSession 就相當於一個數據庫連接(Connection 對象),你可以在一個事務裏面執行多條 SQL,然後通過它的 commit、rollback 等方法,提交或者回滾事務。

所以它應該存活在一個業務請求中,處理完整個請求後,應該關閉這條連接,讓它歸還給 SqlSessionFactory,否則數據庫資源就很快被耗費精光,系統就會癱瘓,所以用 try…catch…finally… 語句來保證其正確關閉。

所以 SqlSession 的最佳的作用域是請求或方法作用域。

Mapper

Mapper 是一個接口,它由 SqlSession 所創建,所以它的最大生命週期至多和 SqlSession 保持一致,儘管它很好用,但是由於 SqlSession 的關閉,它的數據庫連接資源也會消失,所以它的生命週期應該小於等於 SqlSession 的生命週期。Mapper 代表的是一個請求中的業務處理,所以它應該在一個請求中,一旦處理完了相關的業務,就應該廢棄它。

以上,我們討論了 MyBatis 組件的生命週期,如圖所示。

MyBatis組件的生命週期

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章