mybatis最全教程之JAVA API

2020-12-05 計算機java編程

既然你已經知道如何配置 MyBatis 和創建映射文件,你就已經準備好來提升技能了。MyBatis 的 Java API 就是你收穫你所做的努力的地方。正如你即將看到的,和 JDBC 相比,MyBatis 很大程度簡化了你的代碼並保持代碼簡潔,容易理解並維護。MyBatis 3 已經引入了很多重要的改進來使得 SQL 映射更加優秀。

應用目錄結構

在我們深入 Java API 之前,理解關於目錄結構的最佳實踐是很重要的。MyBatis 非常靈活,你可以用你自己的文件來做幾乎所有的事情。但是對於任一框架,都有一些最佳的方式。

讓我們看一下典型的應用目錄結構:

當然這是推薦的目錄結構,並非強制要求,但是使用一個通用的目錄結構將更利於大家溝通。

這部分內容剩餘的示例將假設你使用了這種目錄結構。

SqlSessions

使用 MyBatis 的主要 Java 接口就是 SqlSession。你可以通過這個接口來執行命令,獲取映射器和管理事務。我們會概括討論一下 SqlSession 本身,但是首先我們還是要了解如何獲取一個 SqlSession 實例。SqlSessions 是由 SqlSessionFactory 實例創建的。SqlSessionFactory 對象包含創建 SqlSession 實例的所有方法。而 SqlSessionFactory 本身是由 SqlSessionFactoryBuilder 創建的,它可以從 XML、註解或手動配置 Java 代碼來創建 SqlSessionFactory。

當 Mybatis 與一些依賴注入框架(如 Spring 或者 Guice)同時使用時,SqlSessions 將被依賴注入框架所創建,所以你不需要使用 SqlSessionFactoryBuilder 或者 SqlSessionFactory,可以直接看 SqlSession 這一節。請參考 Mybatis-Spring 或者 Mybatis-Guice 手冊了解更多信息。

SqlSessionFactoryBuilder

SqlSessionFactoryBuilder 有五個 build() 方法,每一種都允許你從不同的資源中創建一個 SqlSession 實例。

第一種方法是最常用的,它使用了一個參照了 XML 文檔或上面討論過的更特定的 mybatis-config.xml 文件的 Reader 實例。可選的參數是 environment 和 properties。environment 決定加載哪種環境,包括數據源和事務管理器。比如:

如果你調用了參數有 environment 的 build 方法,那麼 MyBatis 將會使用 configuration 對象來配置這個 environment。當然,如果你指定了一個不合法的 environment,你就會得到錯誤提示。如果你調用了不帶 environment 參數的 build 方法,那麼就使用默認的 environment(在上面的示例中指定為 default="development" 的代碼)。

如果你調用了參數有 properties 實例的方法,那麼 MyBatis 就會加載那些 properties(屬性配置文件),並在配置中可用。那些屬性可以用${propName} 語法形式多次用在配置文件中。

回想一下,屬性可以從 mybatis-config.xml 中被引用,或者直接指定它。因此理解優先級是很重要的。我們在文檔前面已經提及它了,但是這裡要再次重申:

如果一個屬性存在於這些位置,那麼 MyBatis 將會按照下面的順序來加載它們:

首先讀取在 properties 元素體中指定的屬性; 其次,讀取從 properties 元素的類路徑 resource 或 url 指定的屬性,且會覆蓋已經指定了的重複屬性;最後,讀取作為方法參數傳遞的屬性,且會覆蓋已經從 properties 元素體和 resource 或 url 屬性中加載了的重複屬性。

因此,通過方法參數傳遞的屬性的優先級最高,resource 或 url 指定的屬性優先級中等,在 properties 元素體中指定的屬性優先級最低。

總結一下,前四個方法很大程度上是相同的,但是由於覆蓋機制,便允許你可選地指定 environment 和/或 properties。以下給出一個從 mybatis-config.xml 文件創建 SqlSessionFactory 的示例:

注意到這裡我們使用了 Resources 工具類,這個類在 org.apache.ibatis.io 包中。Resources 類正如其名,會幫助你從類路徑下、文件系統或一個 web URL 中加載資源文件。看一下這個類的原始碼或者通過你的 IDE 來查看,就會看到一整套相當實用的方法。這裡給出一個簡表:

最後一個 build 方法的參數為 Configuration 實例。configuration 類包含你可能需要了解 SqlSessionFactory 實例的所有內容。Configuration 類對於配置的自查很有用,它包含查找和操作 SQL 映射(當應用接收請求時便不推薦使用)。作為一個 Java API 的 configuration 類具有所有配置的開關,這些你已經了解了。這裡有一個簡單的示例,教你如何手動配置 configuration 實例,然後將它傳遞給 build() 方法來創建 SqlSessionFactory。

現在你就獲得一個可以用來創建 SqlSession 實例的 SqlSessionFactory 了!

SqlSessionFactory

SqlSessionFactory 有六個方法創建 SqlSession 實例。通常來說,當你選擇這些方法時你需要考慮以下幾點:

事務處理:我需要在 session 使用事務或者使用自動提交功能(auto-commit)嗎?(通常意味著很多資料庫和/或 JDBC 驅動沒有事務)連接:我需要依賴 MyBatis 獲得來自數據源的配置嗎?還是使用自己提供的配置?執行語句:我需要 MyBatis 復用預處理語句和/或批量更新語句(包括插入和刪除)嗎?

基於以上需求,有下列已重載的多個 openSession() 方法供使用。

默認的 openSession()方法沒有參數,它會創建有如下特性的 SqlSession:

會開啟一個事務(也就是不自動提交)。 將從由當前環境配置的 DataSource 實例中獲取 Connection 對象。事務隔離級別將會使用驅動或數據源的默認設置。預處理語句不會被復用,也不會批量處理更新。

這些方法大都是可讀性強的。向 autoCommit 可選參數傳遞 true 值即可開啟自動提交功能。若要使用自己的 Connection 實例,傳遞一個 Connection 實例給 connection 參數即可。注意並未覆寫同時設置 Connection 和 autoCommit 兩者的方法,因為 MyBatis 會使用正在使用中的、設置了 Connection 的環境。MyBatis 為事務隔離級別調用使用了一個 Java 枚舉包裝器,稱為 TransactionIsolationLevel,若不使用它,將使用 JDBC 所支持五個隔離級(NONE、READ_UNCOMMITTED、READ_COMMITTED、REPEATABLE_READ 和 SERIALIZABLE),並按它們預期的方式來工作。

還有一個可能對你來說是新見到的參數,就是 ExecutorType。這個枚舉類型定義了三個值:

ExecutorType.SIMPLE:這個執行器類型不做特殊的事情。它為每個語句的執行創建一個新的預處理語句。ExecutorType.REUSE:這個執行器類型會復用預處理語句。ExecutorType.BATCH:這個執行器會批量執行所有更新語句,如果 SELECT 在它們中間執行,必要時請把它們區分開來以保證行為的易讀性。

在 SqlSessionFactory 中還有一個方法我們沒有提及,就是 getConfiguration()。這個方法會返回一個 Configuration 實例,在運行時你可以使用它來自檢 MyBatis 的配置。

如果你使用的是 MyBatis 之前的版本,你要重新調用 openSession,因為舊版本的 session、事務和批量操作是分離開來的。如果使用的是新版本,那麼就不必這麼做了,因為它們現在都包含在 session 的作用域內了。你不必再單獨處理事務或批量操作就能得到想要的全部效果。

SqlSession

正如上面所提到的,SqlSession 實例在 MyBatis 中是非常強大的一個類。在這裡你會看到所有執行語句、提交或回滾事務和獲取映射器實例的方法。

在 SqlSession 類中有超過 20 個方法,所以將它們組合成易於理解的分組。

執行語句方法

這些方法被用來執行定義在 SQL 映射的 XML 文件中的 SELECT、INSERT、UPDATE 和 DELETE 語句。它們都會自行解釋,每一句都使用語句的 ID 屬性和參數對象,參數可以是原生類型(自動裝箱或包裝類)、JavaBean、POJO 或 Map。

selectOne 和 selectList 的不同僅僅是 selectOne 必須返回一個對象或 null 值。如果返回值多於一個,那麼就會拋出異常。如果你不知道返回對象的數量,請使用 selectList。如果需要查看返回對象是否存在,可行的方案是返回一個值即可(0 或 1)。selectMap 稍微特殊一點,因為它會將返回的對象的其中一個屬性作為 key 值,將對象作為 value 值,從而將多結果集轉為 Map 類型值。因為並不是所有語句都需要參數,所以這些方法都重載成不需要參數的形式。

最後,還有 select 方法的三個高級版本,它們允許你限制返回行數的範圍,或者提供自定義結果控制邏輯,這通常在數據集合龐大的情形下使用。

RowBounds 參數會告訴 MyBatis 略過指定數量的記錄,還有限制返回結果的數量。RowBounds 類有一個構造方法來接收 offset 和 limit,另外,它們是不可二次賦值的。

所以在這方面,不同的驅動能夠取得不同級別的高效率。為了取得最佳的表現,請使用結果集的 SCROLL_SENSITIVE 或 SCROLL_INSENSITIVE 的類型(換句話說:不用 FORWARD_ONLY)。

ResultHandler 參數允許你按你喜歡的方式處理每一行。你可以將它添加到 List 中、創建 Map 和 Set,或者丟棄每個返回值都可以,它取代了僅保留執行語句過後的總結果列表的死板結果。你可以使用 ResultHandler 做很多事,並且這是 MyBatis 自身內部會使用的方法,以創建結果集列表。

Since 3.4.6, ResultHandler passed to a CALLABLE statement is used on every REFCURSOR output parameter of the stored procedure if there is any.

它的接口很簡單。

ResultContext 參數允許你訪問結果對象本身、被創建的對象數目、以及返回值為 Boolean 的 stop 方法,你可以使用此 stop 方法來停止 MyBatis 加載更多的結果。

使用 ResultHandler 的時候需要注意以下兩種限制:

從被 ResultHandler 調用的方法返回的數據不會被緩存。當使用結果映射集(resultMap)時,MyBatis 大多數情況下需要數行結果來構造外鍵對象。如果你正在使用 ResultHandler,你可以給出外鍵(association)或者集合(collection)尚未賦值的對象。

批量立即更新方法

有一個方法可以刷新(執行)存儲在 JDBC 驅動類中的批量更新語句。當你將 ExecutorType.BATCH 作為 ExecutorType 使用時可以採用此方法。

事務控制方法

控制事務作用域有四個方法。當然,如果你已經設置了自動提交或你正在使用外部事務管理器,這就沒有任何效果了。然而,如果你正在使用 JDBC 事務管理器,由Connection 實例來控制,那麼這四個方法就會派上用場:

默認情況下 MyBatis 不會自動提交事務,除非它偵測到有插入、更新或刪除操作改變了資料庫。如果你已經做出了一些改變而沒有使用這些方法,那麼你可以傳遞 true 值到 commit 和 rollback 方法來保證事務被正常處理(注意,在自動提交模式或者使用了外部事務管理器的情況下設置 force 值對 session 無效)。很多時候你不用調用 rollback(),因為 MyBatis 會在你沒有調用 commit 時替你完成回滾操作。然而,如果你需要在支持多提交和回滾的 session 中獲得更多細粒度控制,你可以使用回滾操作來達到目的。

注意 MyBatis-Spring 和 MyBatis-Guice 提供了聲明事務處理,所以如果你在使用 Mybatis 的同時使用了Spring 或者 Guice,那麼請參考它們的手冊以獲取更多的內容。

本地緩存

Mybatis 使用到了兩種緩存:本地緩存(local cache)和二級緩存(second level cache)。

每當一個新 session 被創建,MyBatis 就會創建一個與之相關聯的本地緩存。任何在 session 執行過的查詢語句本身都會被保存在本地緩存中,那麼,相同的查詢語句和相同的參數所產生的更改就不會二度影響資料庫了。本地緩存會被增刪改、提交事務、關閉事務以及關閉 session 所清空。

默認情況下,本地緩存數據可在整個 session 的周期內使用,這一緩存需要被用來解決循環引用錯誤和加快重複嵌套查詢的速度,所以它可以不被禁用掉,但是你可以設置 localCacheScope=STATEMENT 表示緩存僅在語句執行時有效。

注意,如果 localCacheScope 被設置為 SESSION,那麼 MyBatis 所返回的引用將傳遞給保存在本地緩存裡的相同對象。對返回的對象(例如 list)做出任何更新將會影響本地緩存的內容,進而影響存活在 session 生命周期中的緩存所返回的值。因此,不要對 MyBatis 所返回的對象作出更改,以防後患。

你可以隨時調用以下方法來清空本地緩存:

確保 SqlSession 被關閉

你必須保證的最重要的事情是你要關閉所打開的任何 session。保證做到這點的最佳方式是下面的工作模式:

還有,如果你正在使用jdk 1.7以上的版本還有MyBatis 3.2以上的版本,你可以使用try-with-resources語句:

就像 SqlSessionFactory,你可以通過調用當前使用中的 SqlSession 的 getConfiguration 方法來獲得 Configuration 實例。

使用映射器

上述的各個 insert、update、delete 和 select 方法都很強大,但也有些繁瑣,可能會產生類型安全問題並且對於你的 IDE 和單元測試也沒有實質性的幫助。在上面的入門章節中我們已經看到了一個使用映射器的示例。

因此,一個更通用的方式來執行映射語句是使用映射器類。一個映射器類就是一個僅需聲明與 SqlSession 方法相匹配的方法的接口類。下面的示例展示了一些方法籤名以及它們是如何映射到 SqlSession 上的。

總之,每個映射器方法籤名應該匹配相關聯的 SqlSession 方法,而字符串參數 ID 無需匹配。相反,方法名必須匹配映射語句的 ID。

此外,返回類型必須匹配期望的結果類型,單返回值時為所指定類的值,多返回值時為數組或集合。所有常用的類型都是支持的,包括:原生類型、Map、POJO 和 JavaBean。

映射器接口不需要去實現任何接口或繼承自任何類。只要方法可以被唯一標識對應的映射語句就可以了。

映射器接口可以繼承自其他接口。當使用 XML 來構建映射器接口時要保證語句被包含在合適的命名空間中。而且,唯一的限制就是你不能在兩個繼承關係的接口中擁有相同的方法籤名(潛在的危險做法不可取)。

你可以傳遞多個參數給一個映射器方法。如果你這樣做了,默認情況下它們將會以 "param" 字符串緊跟著它們在參數列表中的位置來命名,比如:#{param1}、#{param2}等。如果你想改變參數的名稱(只在多參數情況下),那麼你可以在參數上使用 @Param("paramName") 註解。

你也可以給方法傳遞一個 RowBounds 實例來限制查詢結果。

映射器註解

因為最初設計時,MyBatis 是一個 XML 驅動的框架。配置信息是基於 XML 的,而且映射語句也是定義在 XML 中的。而到了 MyBatis 3,就有新選擇了。MyBatis 3 構建在全面且強大的基於 Java 語言的配置 API 之上。這個配置 API 是基於 XML 的 MyBatis 配置的基礎,也是新的基於註解配置的基礎。註解提供了一種簡單的方式來實現簡單映射語句,而不會引入大量的開銷。

注意 不幸的是,Java 註解的的表達力和靈活性十分有限。儘管很多時間都花在調查、設計和試驗上,最強大的 MyBatis 映射並不能用註解來構建——並不是在開玩笑,的確是這樣。比方說,C#屬性就沒有這些限制,因此 MyBatis.NET 將會比 XML 有更豐富的選擇。也就是說,基於 Java 註解的配置離不開它的特性。

註解如下表所示:

映射申明樣例

這個例子展示了如何使用 @SelectKey 註解來在插入前讀取資料庫序列的值:

這個例子展示了如何使用 @SelectKey 註解來在插入後讀取資料庫識別列的值:

這個例子展示了如何使用 @Flush 註解去調用 SqlSession#flushStatements():

這些例子展示了如何通過指定 @Result 的 id 屬性來命名結果集:

這個例子展示了單一參數使用 @SqlProvider 註解:

這個例子展示了多參數使用 @SqlProvider 註解:

相關焦點

  • 徹底搞懂MyBatis插件原理及PageHelper原理
    *;import org.apache.ibatis.session.ResultHandler;import org.apache.ibatis.session.RowBounds;import java.util.Properties;@Intercepts({@Signature(type = Executor.class,method= "query",args = {MappedStatement.class
  • Java基礎教程:java反射機制教程
    請看下面的代碼: 這是一個最簡單不過的類,當我們使用的時候直接new出來一個User對象即可。這時候java語言在設計的時候為我們提供了一個機制,就是反射機制,他能夠很方便的去解決我們的問題。
  • 使用C#的後端Web API:循序漸進教程
    為伺服器後端邏輯選擇語言的問題是幾乎每個開發人員最重要的問題之一,特別是對於初學者。目前已經有很多不同的語言:Java,.NET(C#,VD),Ruby,Python,Perl,JavaScript(Node.js),Go,C ++。
  • 「JAVA」萬字長篇詳述字節碼對象與反射機制完成動態編程
    1.類的加載類的加載是指將類的class文件(字節碼文件)載入JVM內存中,並為之創建一個java.lang.Class對象,也就是字節碼對象。,通過調用api,便能獲取運行時的類信息;Java 中通過java.lang.reflect類庫來支持反射;03
  • smart-doc 1.9.7 發布,Java 零註解文檔生成工具
    smart-doc是一款同時支持java restful api和apache dubbo rpc接口文檔生成的工具
  • Java 生成隨機數的 5 種方式,你知道幾種?
    關注公眾號Java技術棧回復 java 獲取更多 Java 工具類教程。 不是直接用 實例化,而是第一次使用其靜態方法 得到 實例,然後調用 類提供的方法獲得各種隨機數。 使用: 結果: 4. java.Security.SecureRandom 也是繼承至 java.util.Random。
  • java基礎教程:Collection集合,Collection 常用API
    集合:集合是java中提供的一種容器,可以用來存儲多個數據。集合和數組既然都是容器,它們有什麼區別呢?數組的長度是固定的。集合的長度是可變的。數組中存儲的是同一類型的元素,可以存儲任意類型數據。集合存儲的都是引用數據類型。如果想存儲基本類型數據需要存儲對應的包裝類型。
  • 俠說java8-LocalDateTime等時間使用手冊(全),先mark後看
    前言java8的時間日期api給我們提供了極大的便利。如何更好的熟悉使用時間api也是學習java8的一個很重要的知識點,下面我們一起來學習學習。本篇文章代碼比較多,可以作為工具,需要使用時,再來查閱。目錄1.普通Date時間如何轉為LocalDateTime?
  • Mybatis中類型映射處理器詳解
    資料庫廠商標識接上一篇文章分析,下一個解析的是databaseIdProvider節點,這個節點好理解,從字面理解就是資料庫提供商的id,也就是mybatis需要訪問的資料庫是那種資料庫。我們都知道mybatis只是一個ORM框架,並不是針對具體的資料庫,需要兼容多種資料庫,所以mybatis可以根據不同的資料庫廠商執行不同的語句,這種多廠商的支持是基於映射語句中的 databaseId 屬性。
  • ECharts-Java 類庫 2.2.6 版本發布
    下載地址ECharts-x.x.x.jarAPI文檔-2.2.6 下載後解壓即可項目支持圖表類型 =================================更新日誌: 2.2.6 由於echarts.js-2.2.5版本只是修復bug,對本項目沒有影響,可以直接用echarts-java
  • Rocket-API 2.3.2 發布,基於 spring boot 的 API 敏捷開發框架
    功能新增或修改: 遠程部署重複判斷 添加mongo對象操作函數 mapping路徑匹配修改,解決restful下路徑可能會匹配執行邏輯錯誤問題 增加配置項 駝峰轉換配置 spring.rocket-api.map-underscore-to-camel-case
  • Java 反射最佳實踐
    測試代碼:https://github.com/jOOQ/jOOR/tree/master/jOOR/src/test/java/org/joor/test固定連接:https://github.com/tianzhijiexian/Android-Best-Practices/blob/master/2015.9
  • getty 發布,一個完全基於 java 實現的 aio 框架
    3、本人對netty比較喜歡,無論是其性能還是編程思想(JBOSS提供的一個java開源網絡框架,可以說是java網絡通訊裡的一哥,極其穩定和強大的性能使得被廣泛使用)4、有了netty為何還要自己造輪子?這裡有兩個原因,其一是本人就喜歡造輪子,這是病,改不了。
  • Java開發人員必知必會的20種常用類庫和API
    在本文中,我將分享一些Java開發人員應該熟悉的最有用的和必要的庫和API。順便說一句,這裡不包括框架,如Spring和Hibernate因為他們非常有名,都有特定的功能。本文總結了日誌、JSON解析、單測、XML解析、字節碼處理、資料庫連接池、集合類、郵件、加密、嵌入式SQL資料庫、JDBC故障診斷以及序列化等20個方面的常用類庫。
  • MyBatis dynamic SQL 1.1.4 發布,生成動態 SQL 的框架
    此版本包含兩項增強功能: 支持在計數、刪除、選擇和更新語句之間共享 where 子句 改進 Kotlin DSL - 刪除了一些引起歧義的擴展方法,並添加了自定義構建器以及一項 bug 修復: 修復了以下錯誤:在子查詢中首先使用限制/偏移/獲取會導致參數名稱衝突完整更新內容可查看:https://github.com/mybatis/mybatis-dynamic-sql
  • Java API + Python AI,實現跨平臺任務調度
    API接口服務├── controller│ └── CheckController.java├── mq│ └── MqService.java│ └── MqConsumer.java3,MqConsumer.java接收任務處理狀態消息,使用的是發布訂閱消息Topic4,配置完成後,啟動API服務,運行單元測試驗證消息發送接收功能5,API服務接收到的狀態信息四,AI業務處理服務
  • MyBatis Dynamic SQL 1.0.0,生成動態 SQL 語句的框架
    最常見的用例是生成語句和一組匹配的參數,這些參數可以被 MyBatis 直接使用。該庫還將生成與 Spring JDBC 模板兼容的語句和參數對象。該庫通過實現一個類似 SQL 的 DSL 來創建一個對象,該對象包含完整的 SQL 語句以及該語句所需的任何參數。SQL 語句對象可以被 MyBatis 直接用作映射器方法的參數。
  • Java學習必不可少的十大網站
    這是我為學習java的同學們準備的網站集合。這些網站提供新聞,常見問題或訪談問題的答案,精彩的講座等。質量是好的網站的關鍵因素。我認為它們都具有最高的質量。在下文中,我還將分享如何使用這些網站進行學習或娛樂。1.
  • 淺談Java中的幾種隨機數
    眾所周知,隨機數是任何一種程式語言最基本的特徵之一。而生成隨機數的基本方式也是相同的:產生一個0到1之間的隨機數。看似簡單,但有時我們也會忽略了一些有趣的功能。我們從書本上學到什麼?最明顯的,也是直觀的方式,在Java中生成隨機數隻要簡單的調用:java.lang.Math.random() 在所有其他語言中,生成隨機數就像是使用Math工具類,如abs, pow, floor, sqrt和其他數學函數。大多數人通過書籍、教程和課程來了解這個類。一個簡單的例子:從0.0到1.0之間可以生成一個雙精度浮點數。
  • 人類探索馬利亞亞納海溝的最深處,發現了什麼?西瓜視頻帶你揭秘
    useUnicode=true&characterEncoding=utf8cluster.datasource.username=rootcluster.datasource.password=123456cluster.datasource.driverClassName=com.mysql.jdbc.Driver 初始化大小,最小,最大  spring.datasource.type