Mybatis-JavaAPI

 

Java API

 

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

應用目錄結構

 

在咱們深刻 Java API 以前,理解關於目錄結構的最佳實踐是很重要的。MyBatis 很是靈活,你能夠用你本身的文件來作幾乎全部的事情。可是對於任一框架,都有一些最佳的方式。  web

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

/my_application
  /bin
  /devlib
  /lib                <-- MyBatis *.jar 文件在這裏。
  /src
    /org/myapp/
      /action
      /data           <-- MyBatis 配置文件在這裏, 包括映射器類, XML 配置, XML 映射文件。
        /mybatis-config.xml
        /BlogMapper.java
        /BlogMapper.xml
      /model
      /service
      /view
    /properties       <-- 在你 XML 中配置的屬性文件在這裏。
  /test
    /org/myapp/
      /action
      /data
      /model
      /service
      /view
    /properties
  /web
    /WEB-INF
      /web.xml

固然這是推薦的目錄結構,並不是強制要求,可是使用一個通用的目錄結構將更利於你們溝通。數據庫

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

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 實例。安全

SqlSessionFactory build(InputStream inputStream) SqlSessionFactory build(InputStream inputStream, String environment) SqlSessionFactory build(InputStream inputStream, Properties properties) SqlSessionFactory build(InputStream inputStream, String env, Properties props) SqlSessionFactory build(Configuration config)
    

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

<environments default="development"> <environment id="development"> <transactionManager type="JDBC"> ... <dataSource type="POOLED"> ... </environment> <environment id="production"> <transactionManager type="MANAGED"> ... <dataSource type="JNDI"> ... </environment> </environments>
    

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

   

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

 

回想一下,屬性能夠從 mybatis-config.xml 中被引用,或者直接指定它。所以理解優先級是很重要的。咱們在文檔前面已經說起它了,可是這裏要再次重申:


 

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

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

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


 

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

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

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

URL getResourceURL(String resource) URL getResourceURL(ClassLoader loader, String resource) InputStream getResourceAsStream(String resource) InputStream getResourceAsStream(ClassLoader loader, String resource) Properties getResourceAsProperties(String resource) Properties getResourceAsProperties(ClassLoader loader, String resource) Reader getResourceAsReader(String resource) Reader getResourceAsReader(ClassLoader loader, String resource) File getResourceAsFile(String resource) File getResourceAsFile(ClassLoader loader, String resource) InputStream getUrlAsStream(String urlString) Reader getUrlAsReader(String urlString) Properties getUrlAsProperties(String urlString) Class classForName(String className)
 

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

DataSource dataSource = BaseDataTest.createBlogDataSource(); TransactionFactory transactionFactory = new JdbcTransactionFactory(); Environment environment = new Environment("development", transactionFactory, dataSource); Configuration configuration = new Configuration(environment); configuration.setLazyLoadingEnabled(true); configuration.setEnhancementEnabled(true); configuration.getTypeAliasRegistry().registerAlias(Blog.class); configuration.getTypeAliasRegistry().registerAlias(Post.class); configuration.getTypeAliasRegistry().registerAlias(Author.class); configuration.addMapper(BoundBlogMapper.class); configuration.addMapper(BoundAuthorMapper.class); SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder(); SqlSessionFactory factory = builder.build(configuration);
 

如今你就得到一個能夠用來建立 SqlSession 實例的 SqlSessionFactory 了!

SqlSessionFactory

 

SqlSessionFactory 有六個方法建立 SqlSession 實例。一般來講,當你選擇這些方法時你須要考慮如下幾點:

       
  • 事務處理:我須要在 session 使用事務或者使用自動提交功能(auto-commit)嗎?(一般意味着不少數據庫和/或 JDBC 驅動沒有事務)
  •    
  • 鏈接:我須要依賴 MyBatis 得到來自數據源的配置嗎?仍是使用本身提供的配置?
  •    
  • 執行語句:我須要 MyBatis 複用預處理語句和/或批量更新語句(包括插入和刪除)嗎?
 

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

SqlSession openSession() SqlSession openSession(boolean autoCommit) SqlSession openSession(Connection connection) SqlSession openSession(TransactionIsolationLevel level) SqlSession openSession(ExecutorType execType,TransactionIsolationLevel level) SqlSession openSession(ExecutorType execType) SqlSession openSession(ExecutorType execType, boolean autoCommit) SqlSession openSession(ExecutorType execType, Connection connection) Configuration getConfiguration();
 

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

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

這些方法大都是可讀性強的。向 autoCommit 可選參數傳遞 true 值便可開啓自動提交功能。若要使用本身的 Connection 實例,傳遞一個 Connection 實例給 connection 參數便可。注意並未覆寫同時設置 ConnectionautoCommit 二者的方法,由於 MyBatis 會使用正在使用中的、設置了 Connection 的環境。MyBatis 爲事務隔離級別調用使用了一個 Java 枚舉包裝器,稱爲 TransactionIsolationLevel,若不使用它,將使用 JDBC 所支持五個隔離級(NONEREAD_UNCOMMITTEDREAD_COMMITTEDREPEATABLE_READSERIALIZABLE),並按它們預期的方式來工做。

 

還有一個可能對你來講是新見到的參數,就是 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。

<T> T selectOne(String statement, Object parameter) <E> List<E> selectList(String statement, Object parameter) <K,V> Map<K,V> selectMap(String statement, Object parameter, String mapKey) int insert(String statement, Object parameter) int update(String statement, Object parameter) int delete(String statement, Object parameter)
 

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

<T> T selectOne(String statement) <E> List<E> selectList(String statement) <K,V> Map<K,V> selectMap(String statement, String mapKey) int insert(String statement) int update(String statement) int delete(String statement)
 

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

<E> List<E> selectList (String statement, Object parameter, RowBounds rowBounds) <K,V> Map<K,V> selectMap(String statement, Object parameter, String mapKey, RowBounds rowbounds) void select (String statement, Object parameter, ResultHandler<T> handler) void select (String statement, Object parameter, RowBounds rowBounds, ResultHandler<T> handler)
 

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

int offset = 100; int limit = 25; RowBounds rowBounds = new 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.

它的接口很簡單。

package org.apache.ibatis.session; public interface ResultHandler<T> { void handleResult(ResultContext<? extends T> context); }

ResultContext 參數容許你訪問結果對象自己、被建立的對象數目、以及返回值爲 Boolean 的 stop 方法,你可使用此 stop 方法來中止 MyBatis 加載更多的結果。

 

使用 ResultHandler 的時候須要注意如下兩種限制:

     
  • 從被 ResultHandler 調用的方法返回的數據不會被緩存。
  •  
  • 當使用結果映射集(resultMap)時,MyBatis 大多數狀況下須要數行結果來構造外鍵對象。若是你正在使用 ResultHandler,你能夠給出外鍵(association)或者集合(collection)還沒有賦值的對象。
批量當即更新方法

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

List<BatchResult> flushStatements()
事務控制方法

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

void commit() void commit(boolean force) void rollback() void rollback(boolean force)

默認狀況下 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 所返回的對象做出更改,以防後患。

你能夠隨時調用如下方法來清空本地緩存:

 
void clearCache()
確保 SqlSession 被關閉
void close()

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

SqlSession session = sqlSessionFactory.openSession(); try { // following 3 lines pseudocod for "doing some work" session.insert(...); session.update(...); session.delete(...); session.commit(); } finally { session.close(); }

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

try (SqlSession session = sqlSessionFactory.openSession()) { // following 3 lines pseudocode for "doing some work" session.insert(...); session.update(...); session.delete(...); session.commit(); }
 

注意 就像 SqlSessionFactory,你能夠經過調用當前使用中的 SqlSession 的 getConfiguration 方法來得到 Configuration 實例。

Configuration getConfiguration()
使用映射器
<T> T getMapper(Class<T> type)

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

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

public interface AuthorMapper { // (Author) selectOne("selectAuthor",5); Author selectAuthor(int id); // (List<Author>) selectList(「selectAuthors」) List<Author> selectAuthors(); // (Map<Integer,Author>) selectMap("selectAuthors", "id") @MapKey("id") Map<Integer, Author> selectAuthors(); // insert("insertAuthor", author) int insertAuthor(Author author); // updateAuthor("updateAuthor", author) int updateAuthor(Author author); // delete("deleteAuthor",5) int deleteAuthor(int id); }

總之,每一個映射器方法簽名應該匹配相關聯的 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 註解的配置離不開它的特性。

 

註解以下表所示:

                                                                                                                                                       
註解 使用對象 相對應的 XML 描述
@CacheNamespace <cache> 爲給定的命名空間(好比類)配置緩存。屬性有:implemetation, eviction, flushInterval, size, readWrite, blockingproperties
@Property N/A <property> 指定參數值或佔位值(placeholder)(能被 mybatis-config.xml內的配置屬性覆蓋)。屬性有:name, value。(僅在MyBatis 3.4.2以上版本生效)
@CacheNamespaceRef <cacheRef> 參照另一個命名空間的緩存來使用。屬性有:value, name。若是你使用了這個註解,你應設置 value 或者 name 屬性的其中一個。value 屬性用於指定 Java 類型而指定命名空間(命名空間名就是指定的 Java 類型的全限定名),name 屬性(這個屬性僅在MyBatis 3.4.2以上版本生效)直接指定了命名空間的名字。
@ConstructorArgs 方法 <constructor> 收集一組結果傳遞給一個結果對象的構造方法。屬性有:value,它是形式參數數組。
@Arg N/A
  • <arg>
  • <idArg>
單參數構造方法,是 ConstructorArgs 集合的一部分。屬性有:id, column, javaType, jdbcType, typeHandler, selectresultMap。id 屬性是布爾值,來標識用於比較的屬性,和<idArg> XML 元素類似。
@TypeDiscriminator 方法 <discriminator> 一組實例值被用來決定結果映射的表現。屬性有:column, javaType, jdbcType, typeHandlercases。cases 屬性是實例數組。
@Case N/A <case> 單獨實例的值和它對應的映射。屬性有:value, type, results。results 屬性是結果數組,所以這個註解和實際的 ResultMap 很類似,由下面的 Results 註解指定。
@Results 方法 <resultMap> 結果映射的列表,包含了一個特別結果列如何被映射到屬性或字段的詳情。屬性有:value, id。value 屬性是 Result 註解的數組。這個 id 的屬性是結果映射的名稱。
@Result N/A
  • <result>
  • <id>
在列和屬性或字段之間的單獨結果映射。屬性有:id, column, javaType, jdbcType, typeHandler, one, many。id 屬性是一個布爾值,來標識應該被用於比較(和在 XML 映射中的<id>類似)的屬性。one 屬性是單獨的聯繫,和 <association> 類似,而 many 屬性是對集合而言的,和<collection>類似。它們這樣命名是爲了不名稱衝突。
@One N/A <association> 複雜類型的單獨屬性值映射。屬性有:select,已映射語句(也就是映射器方法)的全限定名,它能夠加載合適類型的實例。fetchType會覆蓋全局的配置參數 lazyLoadingEnabled注意 聯合映射在註解 API中是不支持的。這是由於 Java 註解的限制,不容許循環引用。
@Many N/A <collection> 映射到複雜類型的集合屬性。屬性有:select,已映射語句(也就是映射器方法)的全限定名,它能夠加載合適類型的實例的集合,fetchType 會覆蓋全局的配置參數 lazyLoadingEnabled注意 聯合映射在註解 API中是不支持的。這是由於 Java 註解的限制,不容許循環引用
@MapKey 方法   這是一個用在返回值爲 Map 的方法上的註解。它可以將存放對象的 List 轉化爲 key 值爲對象的某一屬性的 Map。屬性有: value,填入的是對象的屬性名,做爲 Map 的 key 值。
@Options 方法 映射語句的屬性 這個註解提供訪問大範圍的交換和配置選項的入口,它們一般在映射語句上做爲屬性出現。Options 註解提供了通俗易懂的方式來訪問它們,而不是讓每條語句註解變複雜。屬性有:useCache=true, flushCache=FlushCachePolicy.DEFAULT, resultSetType=FORWARD_ONLY, statementType=PREPARED, fetchSize=-1, timeout=-1, useGeneratedKeys=false, keyProperty="id", keyColumn="", resultSets=""。值得一提的是, Java 註解沒法指定 null 值。所以,一旦你使用了 Options 註解,你的語句就會被上述屬性的默認值所影響。要注意避免默認值帶來的預期之外的行爲。
       注意: keyColumn 屬性只在某些數據庫中有效(如 Oracle、PostgreSQL等)。請在插入語句一節查看更多關於 keyColumn 和 keyProperty 二者的有效值詳情。
  • @Insert
  • @Update
  • @Delete
  • @Select
方法
  • <insert>
  • <update>
  • <delete>
  • <select>
這四個註解分別表明將會被執行的 SQL 語句。它們用字符串數組(或單個字符串)做爲參數。若是傳遞的是字符串數組,字符串之間先會被填充一個空格再鏈接成單個完整的字符串。這有效避免了以 Java 代碼構建 SQL 語句時的「丟失空格」的問題。然而,你也能夠提早手動鏈接好字符串。屬性有:value,填入的值是用來組成單個 SQL 語句的字符串數組。
  • @InsertProvider
  • @UpdateProvider
  • @DeleteProvider
  • @SelectProvider
方法
  • <insert>
  • <update>
  • <delete>
  • <select>
容許構建動態 SQL。這些備選的 SQL 註解容許你指定類名和返回在運行時執行的 SQL 語句的方法。(自從MyBatis 3.4.6開始,你能夠用 CharSequence 代替 String 來返回類型返回值了。)當執行映射語句的時候,MyBatis 會實例化類並執行方法,類和方法就是填入了註解的值。你能夠把已經傳遞給映射方法了的對象做爲參數,"Mapper interface type" 和 "Mapper method" 會通過 ProviderContext (僅在MyBatis 3.4.5及以上支持)做爲參數值。(MyBatis 3.4及以上的版本,支持多參數傳入)屬性有: type, methodtype 屬性需填入類。method 需填入該類定義了的方法名。注意 接下來的小節將會討論類,能幫助你更輕鬆地構建動態 SQL。
@Param 參數 N/A 若是你的映射方法的形參有多個,這個註解使用在映射方法的參數上就能爲它們取自定義名字。若不給出自定義名字,多參數(不包括 RowBounds 參數)則先以 "param" 做前綴,再加上它們的參數位置做爲參數別名。例如 #{param1}, #{param2},這個是默認值。若是註解是 @Param("person"),那麼參數就會被命名爲 #{person}
@SelectKey 方法 <selectKey> 這個註解的功能與 <selectKey> 標籤徹底一致,用在已經被 @Insert@InsertProvider@Update@UpdateProvider 註解了的方法上。若在未被上述四個註解的方法上做 @SelectKey 註解則視爲無效。若是你指定了 @SelectKey 註解,那麼 MyBatis 就會忽略掉由 @Options 註解所設置的生成主鍵或設置(configuration)屬性。屬性有:statement 填入將會被執行的 SQL 字符串數組,keyProperty 填入將會被更新的參數對象的屬性的值,before 填入 true 或 false 以指明 SQL 語句應被在插入語句的以前仍是以後執行。resultType 填入 keyProperty 的 Java 類型和用 StatementPreparedStatement 和 CallableStatement 中的 STATEMENTPREPARED 或 CALLABLE 中任一值填入 statementType。默認值是 PREPARED
@ResultMap 方法 N/A 這個註解給 @Select 或者 @SelectProvider 提供在 XML 映射中的 <resultMap> 的id。這使得註解的 select 能夠複用那些定義在 XML 中的 ResultMap。若是同一 select 註解中還存在 @Results 或者 @ConstructorArgs,那麼這兩個註解將被此註解覆蓋。
@ResultType 方法 N/A 此註解在使用告終果處理器的狀況下使用。在這種狀況下,返回類型爲 void,因此 Mybatis 必須有一種方式決定對象的類型,用於構造每行數據。若是有 XML 的結果映射,請使用 @ResultMap 註解。若是結果類型在 XML 的 <select> 節點中指定了,就不須要其餘的註解了。其餘狀況下則使用此註解。好比,若是 @Select 註解在一個將使用結果處理器的方法上,那麼返回類型必須是 void 而且這個註解(或者@ResultMap)必選。這個註解僅在方法返回類型是 void 的狀況下生效。
@Flush 方法 N/A 若是使用了這個註解,定義在 Mapper 接口中的方法可以調用 SqlSession#flushStatements() 方法。(Mybatis 3.3及以上)
映射申明樣例

這個例子展現瞭如何使用 @SelectKey 註解來在插入前讀取數據庫序列的值:

@Insert("insert into table3 (id, name) values(#{nameId}, #{name})") @SelectKey(statement="call next value for TestSequence", keyProperty="nameId", before=true, resultType=int.class) int insertTable3(Name name);

這個例子展現瞭如何使用 @SelectKey 註解來在插入後讀取數據庫識別列的值:

@Insert("insert into table2 (name) values(#{name})") @SelectKey(statement="call identity()", keyProperty="nameId", before=false, resultType=int.class) int insertTable2(Name name);
 

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

@Flush List<BatchResult> flush();

這些例子展現瞭如何經過指定 @Result 的 id 屬性來命名結果集:

@Results(id = "userResult", value = { @Result(property = "id", column = "uid", id = true), @Result(property = "firstName", column = "first_name"), @Result(property = "lastName", column = "last_name") }) @Select("select * from users where id = #{id}") User getUserById(Integer id); @Results(id = "companyResults") @ConstructorArgs({ @Arg(property = "id", column = "cid", id = true), @Arg(property = "name", column = "name") }) @Select("select * from company where id = #{id}") Company getCompanyById(Integer id);
 

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

@SelectProvider(type = UserSqlBuilder.class, method = "buildGetUsersByName") List<User> getUsersByName(String name); class UserSqlBuilder { public static String buildGetUsersByName(final String name) { return new SQL(){{ SELECT("*"); FROM("users"); if (name != null) { WHERE("name like #{value} || '%'"); } ORDER_BY("id"); }}.toString(); } }
 

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

@SelectProvider(type = UserSqlBuilder.class, method = "buildGetUsersByName") List<User> getUsersByName( @Param("name") String name, @Param("orderByColumn") String orderByColumn); class UserSqlBuilder { // If not use @Param, you should be define same arguments with mapper method public static String buildGetUsersByName( final String name, final String orderByColumn) { return new SQL(){{ SELECT("*"); FROM("users"); WHERE("name like #{name} || '%'"); ORDER_BY(orderByColumn); }}.toString(); } // If use @Param, you can define only arguments to be used public static String buildGetUsersByName(@Param("orderByColumn") final String orderByColumn) { return new SQL(){{ SELECT("*"); FROM("users"); WHERE("name like #{name} || '%'"); ORDER_BY(orderByColumn); }}.toString(); } }
相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息