MyBatis3 入門學習指南


官網原文:http://www.mybatis.org/mybatis-3/zh/index.html 

1.簡介

1.1 什么是 MyBatis?

MyBatis 是一款優秀的持久層框架,它支持定制化 SQL、存儲過程以及高級映射。MyBatis 避免了幾乎所有的 JDBC 代碼和手動設置參數以及獲取結果集。MyBatis 可以使用簡單的 XML 或注解來配置和映射原生類型、接口和 Java 的 POJO(Plain Old Java Objects,普通老式 Java 對象)為數據庫中的記錄。

2.入門

2.1 安裝

要使用 MyBatis, 只需將 mybatis-x.x.x.jar 文件置於 classpath 中即可。

如果使用 Maven 來構建項目,則需將下面的 dependency 代碼置於 pom.xml 文件中:

<dependency>
  <groupId>org.mybatis</groupId>
  <artifactId>mybatis</artifactId>
  <version>x.x.x</version>
</dependency>

 

2.2 從 XML 中構建 SqlSessionFactory

每個基於 MyBatis 的應用都是以一個 SqlSessionFactory 的實例為核心的。SqlSessionFactory 的實例可以通過 SqlSessionFactoryBuilder 獲得。而 SqlSessionFactoryBuilder 則可以從 XML 配置文件或一個預先定制的 Configuration 的實例構建出 SqlSessionFactory 的實例。

從 XML 文件中構建 SqlSessionFactory 的實例非常簡單,建議使用類路徑下的資源文件進行配置。 但是也可以使用任意的輸入流(InputStream)實例,包括字符串形式的文件路徑或者 file:// 的 URL 形式的文件路徑來配置。MyBatis 包含一個名叫 Resources 的工具類,它包含一些實用方法,可使從 classpath 或其他位置加載資源文件更加容易。

String resource = "org/mybatis/example/mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

XML 配置文件中包含了對 MyBatis 系統的核心設置,包含獲取數據庫連接實例的數據源(DataSource)和決定事務作用域和控制方式的事務管理器(TransactionManager)。 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>
  <environments default="development">
    <environment id="development">
      <transactionManager type="JDBC"/>
      <dataSource type="POOLED">
        <property name="driver" value="${driver}"/>
        <property name="url" value="${url}"/>
        <property name="username" value="${username}"/>
        <property name="password" value="${password}"/>
      </dataSource>
    </environment>
  </environments>
  <mappers>
    <mapper resource="org/mybatis/example/BlogMapper.xml"/>
  </mappers>
</configuration>

 

當然,還有很多可以在 XML 文件中進行配置,上面的示例指出的則是最關鍵的部分。 要注意 XML 頭部的聲明,它用來驗證 XML 文檔正確性。environment 元素體中包含了事務管理和連接池的配置。mappers 元素則是包含一組映射器(mapper),這些映射器的 XML 映射文件包含了 SQL 代碼和映射定義信息。

2.3 從 SqlSessionFactory 中獲取 SqlSession

既然有了 SqlSessionFactory,顧名思義,我們就可以從中獲得 SqlSession 的實例了。SqlSession 完全包含了面向數據庫執行 SQL 命令所需的所有方法。你可以通過 SqlSession 實例來直接執行已映射的 SQL 語句。例如:

SqlSession session = sqlSessionFactory.openSession(); try { Blog blog = (Blog) session.selectOne("org.mybatis.example.BlogMapper.selectBlog", 101); } finally { session.close(); }

誠然,這種方式能夠正常工作,並且對於使用舊版本 MyBatis 的用戶來說也比較熟悉。不過現在有了一種更簡潔的方式 ——使用正確描述每個語句的參數和返回值的接口(比如 BlogMapper.class),你現在不僅可以執行更清晰和類型安全的代碼,而且還不用擔心易錯的字符串字面值以及強制類型轉換。

例如:

SqlSession session = sqlSessionFactory.openSession();
try {
  BlogMapper mapper = session.getMapper(BlogMapper.class);
  Blog blog = mapper.selectBlog(101);
} finally {
  session.close();
}

 

現在我們來探究一下這里到底是怎么執行的。

2.4 探究已映射的 SQL 語句

現在你可能很想知道 SqlSession 和 Mapper 到底執行了什么操作,但 SQL 語句映射是個相當大的話題,可能會占去文檔的大部分篇幅。 不過為了讓你能夠了解個大概,這里會給出幾個例子。

在上面提到的例子中,一個語句既可以通過 XML 定義,也可以通過注解定義。我們先看看 XML 定義語句的方式,事實上 MyBatis 提供的全部特性都可以利用基於 XML 的映射語言來實現,這使得 MyBatis 在過去的數年間得以流行。如果你以前用過 MyBatis,你應該對這個概念比較熟悉。 不過自那以后,XML 的配置也改進了許多,我們稍后還會再提到。這里給出一個基於 XML 映射語句的示例,它應該可以滿足上述示例中 SqlSession 的調用。

<?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="org.mybatis.example.BlogMapper">
  <select id="selectBlog" resultType="Blog">
    select * from Blog where id = #{id}
  </select>
</mapper>

 

為了這個簡單的例子,我們似乎寫了不少配置,但實際上它並不多。在一個 XML 映射文件中,可以定義無數個映射語句,這樣一來,XML 頭部和文檔類型聲明占去的部分就顯得微不足道了。而文件的剩余部分具備自解釋性,很容易理解。 在命名空間 “org.mybatis.example.BlogMapper” 中定義了一個名為 “selectBlog” 的映射語句,允許你使用指定的完全限定名 “org.mybatis.example.BlogMapper.selectBlog” 來調用映射語句,就像上面例子中那樣:

Blog blog = (Blog) session.selectOne("org.mybatis.example.BlogMapper.selectBlog", 101);

你可能注意到這和使用完全限定名調用 Java 對象的方法類似。這樣,該命名就可以直接映射到在命名空間中同名的 Mapper 類,並將已映射的 select 語句中的名字、參數和返回類型匹配成方法。 因此你就可以像上面那樣很容易地調用這個對應 Mapper 接口的方法,就像下面這樣:

BlogMapper mapper = session.getMapper(BlogMapper.class);
Blog blog = mapper.selectBlog(101);

第二種方法有很多優勢,首先它不依賴於字符串字面值,會更安全一點; 其次,如果你的 IDE 有代碼補全功能,那么代碼補全可以幫你快速選擇已映射的 SQL 語句。

提示對命名空間的一點說明

在之前版本的 MyBatis 中,命名空間(Namespaces)的作用並不大,是可選的。 但現在,隨着命名空間越發重要,你必須指定命名空間。

命名空間的作用有兩個,一個是利用更長的完全限定名來將不同的語句隔離開來,同時也實現了你上面見到的接口綁定。就算你覺得暫時用不到接口綁定,你也應該遵循這里的規定,以防哪天你改變了主意。 長遠來看,只要將命名空間置於合適的 Java 包命名空間之中,你的代碼會變得更加整潔,也有利於你更方便地使用 MyBatis。

命名解析:為了減少輸入量,MyBatis 對所有的命名配置元素(包括語句,結果映射,緩存等)使用了如下的命名解析規則。

  • 完全限定名(比如 “com.mypackage.MyMapper.selectAllThings)將被直接用於查找及使用。
  • 短名稱(比如 “selectAllThings”)如果全局唯一也可以作為一個單獨的引用。 如果不唯一,有兩個或兩個以上的相同名稱(比如 “com.foo.selectAllThings” 和 “com.bar.selectAllThings”),那么使用時就會產生“短名稱不唯一”的錯誤,這種情況下就必須使用完全限定名。

對於像 BlogMapper 這樣的映射器類來說,還有另一種方法來處理映射。 它們映射的語句可以不用 XML 來配置,而可以使用 Java 注解來配置。比如,上面的 XML 示例可被替換如下:

package org.mybatis.example;
public interface BlogMapper {
  @Select("SELECT * FROM blog WHERE id = #{id}")
  Blog selectBlog(int id);
}

使用注解來映射簡單語句會使代碼顯得更加簡潔,然而對於稍微復雜一點的語句,Java 注解就力不從心了,並且會顯得更加混亂。 因此,如果你需要完成很復雜的事情,那么最好使用 XML 來映射語句。

選擇何種方式來配置映射,以及認為映射語句定義的一致性是否重要,這些完全取決於你和你的團隊。 換句話說,永遠不要拘泥於一種方式,你可以很輕松的在基於注解和 XML 的語句映射方式間自由移植和切換。

2.5 作用域(Scope)和生命周期

理解我們目前已經討論過的不同作用域和生命周期類是至關重要的,因為錯誤的使用會導致非常嚴重的並發問題。


提示 對象生命周期和依賴注入框架

依賴注入框架可以創建線程安全的、基於事務的 SqlSession 和映射器,並將它們直接注入到你的 bean 中,因此可以直接忽略它們的生命周期。 如果對如何通過依賴注入框架來使用 MyBatis 感興趣,可以研究一下 MyBatis-Spring 或 MyBatis-Guice 兩個子項目。


SqlSessionFactoryBuilder

這個類可以被實例化、使用和丟棄,一旦創建了 SqlSessionFactory,就不再需要它了。 因此 SqlSessionFactoryBuilder 實例的最佳作用域是方法作用域(也就是局部方法變量)。 你可以重用 SqlSessionFactoryBuilder 來創建多個 SqlSessionFactory 實例,但是最好還是不要讓其一直存在,以保證所有的 XML 解析資源可以被釋放給更重要的事情。

SqlSessionFactory

SqlSessionFactory 一旦被創建就應該在應用的運行期間一直存在,沒有任何理由丟棄它或重新創建另一個實例。 使用 SqlSessionFactory 的最佳實踐是在應用運行期間不要重復創建多次,多次重建 SqlSessionFactory 被視為一種代碼“壞味道(bad smell)”。因此 SqlSessionFactory 的最佳作用域是應用作用域。 有很多方法可以做到,最簡單的就是使用單例模式或者靜態單例模式。

SqlSession

每個線程都應該有它自己的 SqlSession 實例。SqlSession 的實例不是線程安全的,因此是不能被共享的,所以它的最佳的作用域是請求或方法作用域。 絕對不能將 SqlSession 實例的引用放在一個類的靜態域,甚至一個類的實例變量也不行。 也絕不能將 SqlSession 實例的引用放在任何類型的托管作用域中,比如 Servlet 框架中的 HttpSession。 如果你現在正在使用一種 Web 框架,要考慮 SqlSession 放在一個和 HTTP 請求對象相似的作用域中。 換句話說,每次收到的 HTTP 請求,就可以打開一個 SqlSession,返回一個響應,就關閉它。 這個關閉操作是很重要的,你應該把這個關閉操作放到 finally 塊中以確保每次都能執行關閉。 下面的示例就是一個確保 SqlSession 關閉的標准模式:

SqlSession session = sqlSessionFactory.openSession();
try {
  // 你的應用邏輯代碼
} finally {
  session.close();
}

在你的所有的代碼中一致地使用這種模式來保證所有數據庫資源都能被正確地關閉。

映射器實例

映射器是一些由你創建的、綁定你映射的語句的接口。映射器接口的實例是從 SqlSession 中獲得的。因此從技術層面講,任何映射器實例的最大作用域是和請求它們的 SqlSession 相同的。盡管如此,映射器實例的最佳作用域是方法作用域。 也就是說,映射器實例應該在調用它們的方法中被請求,用過之后即可丟棄。 並不需要顯式地關閉映射器實例,盡管在整個請求作用域保持映射器實例也不會有什么問題,但是你很快會發現,像 SqlSession 一樣,在這個作用域上管理太多的資源的話會難於控制。 為了避免這種復雜性,最好把映射器放在方法作用域內。下面的示例就展示了這個實踐:

SqlSession session = sqlSessionFactory.openSession();
try {
  BlogMapper mapper = session.getMapper(BlogMapper.class);
  // 你的應用邏輯代碼
} finally {
  session.close();
}

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM