正如之前所提到的,?SqlSession
?在 MyBatis 中是非常強大的一個類。它包含了所有執(zhí)行語句、提交或回滾事務以及獲取映射器實例的方法。
?SqlSession
?類的方法超過了 20 個,為了方便理解,我們將它們分成幾種組別。
這些方法被用來執(zhí)行定義在 SQL 映射 XML 文件中的 SELECT、INSERT、UPDATE 和 DELETE 語句。你可以通過名字快速了解它們的作用,每一方法都接受語句的 ID 以及參數(shù)對象,參數(shù)可以是原始類型(支持自動裝箱或包裝類)、JavaBean、POJO 或 Map。
<T> T selectOne(String statement, Object parameter)
<E> List<E> selectList(String statement, Object parameter)
<T> Cursor<T> selectCursor(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
?。如果需要查看某個對象是否存在,最好的辦法是查詢一個 ?count
?值(0 或 1)。?selectMap
?稍微特殊一點,它會將返回對象的其中一個屬性作為 ?key
?值,將對象作為 ?value
?值,從而將多個結果集轉為 ?Map
?類型值。由于并不是所有語句都需要參數(shù),所以這些方法都具有一個不需要參數(shù)的重載形式。
游標(?Cursor
?)與列表(?List
?)返回的結果相同,不同的是,游標借助迭代器實現(xiàn)了數(shù)據的惰性加載。
try (Cursor<MyEntity> entities = session.selectCursor(statement, param)) {
for (MyEntity entity:entities) {
// 處理單個實體
}
}
insert、update 以及 delete 方法返回的值表示受該語句影響的行數(shù)。
<T> T selectOne(String statement)
<E> List<E> selectList(String statement)
<T> Cursor<T> selectCursor(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 方法的三個高級版本,它們允許你限制返回行數(shù)的范圍,或是提供自定義結果處理邏輯,通常在數(shù)據集非常龐大的情形下使用。
<E> List<E> selectList (String statement, Object parameter, RowBounds rowBounds)
<T> Cursor<T> selectCursor(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
?參數(shù)會告訴 MyBatis 略過指定數(shù)量的記錄,并限制返回結果的數(shù)量。?RowBounds
?類的 ?offset
?和 ?limit
?值只有在構造函數(shù)時才能傳入,其它時候是不能修改的。
int offset = 100;
int limit = 25;
RowBounds rowBounds = new RowBounds(offset, limit);
數(shù)據庫驅動決定了略過記錄時的查詢效率。為了獲得最佳的性能,建議將 ?ResultSet
?類型設置為 ?SCROLL_SENSITIVE
?或 ?SCROLL_INSENSITIVE
?(換句話說:不要使用 ?FORWARD_ONLY
?)。
?ResultHandler
?參數(shù)允許自定義每行結果的處理過程。你可以將它添加到 List 中、創(chuàng)建 Map 和 Set,甚至丟棄每個返回值,只保留計算后的統(tǒng)計結果。你可以使用 ?ResultHandler
?做很多事,這其實就是 MyBatis 構建 結果列表的內部實現(xiàn)辦法。
從版本 3.4.6 開始,?ResultHandler
?會在存儲過程的 ?REFCURSOR
?輸出參數(shù)中傳遞使用的 ?CALLABLE
?語句。
它的接口很簡單:
package org.apache.ibatis.session;
public interface ResultHandler<T> {
void handleResult(ResultContext<? extends T> context);
}
?ResultContext
?參數(shù)允許你訪問結果對象和當前已被創(chuàng)建的對象數(shù)目,另外還提供了一個返回值為 ?Boolean
?的 ?stop
?方法,你可以使用此 ?stop
?方法來停止 MyBatis 加載更多的結果。
使用 ?ResultHandler
?的時候需要注意以下兩個限制:
ResultHandler
?參數(shù)的方法時,收到的數(shù)據不會被緩存。resultMap
?)時,MyBatis 很可能需要數(shù)行結果來構造一個對象。如果你使用了 ?ResultHandler
?,你可能會接收到關聯(lián)(?association
?)或者集合(?collection
?)中尚未被完整填充的對象。當你將 ?ExecutorType
?設置為 ?ExecutorType.BATCH
? 時,可以使用這個方法清除(執(zhí)行)緩存在 JDBC 驅動類中的批量更新語句。
List<BatchResult> flushStatements()
有四個方法用來控制事務作用域。當然,如果你已經設置了自動提交或你使用了外部事務管理器,這些方法就沒什么作用了。然而,如果你正在使用由 ?Connection
?實例控制的 JDBC 事務管理器,那么這四個方法就會派上用場:
void commit()
void commit(boolean force)
void rollback()
void rollback(boolean force)
默認情況下 MyBatis 不會自動提交事務,除非它偵測到調用了插入、更新或刪除方法改變了數(shù)據庫。如果你沒有使用這些方法提交修改,那么你可以在 ?commit
?和 ?rollback
?方法參數(shù)中傳入 ?true
?值,來保證事務被正常提交(注意,在自動提交模式或者使用了外部事務管理器的情況下,設置 ?force
?值對 ?session
?無效)。大部分情況下你無需調用 ?rollback()
?,因為 MyBatis 會在你沒有調用 ?commit
?時替你完成回滾操作。不過,當你要在一個可能多次提交或回滾的 ?session
?中詳細控制事務,回滾操作就派上用場了。
Mybatis 使用到了兩種緩存:本地緩存(?local cache
?)和二級緩存(?second level cache
?)。
每當一個新 ?session
?被創(chuàng)建,MyBatis 就會創(chuàng)建一個與之相關聯(lián)的本地緩存。任何在 ?session
?執(zhí)行過的查詢結果都會被保存在本地緩存中,所以,當再次執(zhí)行參數(shù)相同的相同查詢時,就不需要實際查詢數(shù)據庫了。本地緩存將會在做出修改、事務提交或回滾,以及關閉 ?session
?時清空。
默認情況下,本地緩存數(shù)據的生命周期等同于整個 session 的周期。由于緩存會被用來解決循環(huán)引用問題和加快重復嵌套查詢的速度,所以無法將其完全禁用。但是你可以通過設置 ?localCacheScope=STATEMENT
? 來只在語句執(zhí)行時使用緩存。
注意,如果 ?localCacheScope
?被設置為 ?SESSION
?,對于某個對象,MyBatis 將返回在本地緩存中唯一對象的引用。對返回的對象(例如 ?list
?)做出的任何修改將會影響本地緩存的內容,進而將會影響到在本次 ?session
?中從緩存返回的值。因此,不要對 MyBatis 所返回的對象作出更改,以防后患。
你可以隨時調用以下方法來清空本地緩存:
void clearCache()
void close()
對于你打開的任何 ?session
?,你都要保證它們被妥善關閉,這很重要。保證妥善關閉的最佳代碼模式是這樣的:
SqlSession session = sqlSessionFactory.openSession();
try (SqlSession session = sqlSessionFactory.openSession()) {
// 假設下面三行代碼是你的業(yè)務邏輯
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 和單元測試也不是那么友好。因此,使用映射器類來執(zhí)行映射語句是更常見的做法。
我們已經在之前的入門章節(jié)中見到過一個使用映射器的示例。一個映射器類就是一個僅需聲明與 ?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);
}
總之,每個映射器方法簽名應該匹配相關聯(lián)的 ?SqlSession
?方法,字符串參數(shù) ID 無需匹配。而是由方法名匹配映射語句的 ID。
此外,返回類型必須匹配期望的結果類型,返回單個值時,返回類型應該是返回值的類,返回多個值時,則為數(shù)組或集合類,另外也可以是游標(?Cursor
?)。所有常用的類型都是支持的,包括:原始類型、?Map
?、?POJO
?和 ?JavaBean
?。
映射器接口不需要去實現(xiàn)任何接口或繼承自任何類。只要方法簽名可以被用來唯一識別對應的映射語句就可以了。
映射器接口可以繼承自其他接口。在使用 XML 來綁定映射器接口時,保證語句處于合適的命名空間中即可。唯一的限制是,不能在兩個具有繼承關系的接口中擁有相同的方法簽名(這是潛在的危險做法,不可?。?。
你可以傳遞多個參數(shù)給一個映射器方法。在多個參數(shù)的情況下,默認它們將會以 ?param
?加上它們在參數(shù)列表中的位置來命名,比如:?#{param1}
?、?#{param2}
?等。如果你想(在有多個參數(shù)時)自定義參數(shù)的名稱,那么你可以在參數(shù)上使用 ?@Param("paramName")
? 注解。
你也可以給方法傳遞一個 ?RowBounds
?實例來限制查詢結果。
設計初期的 MyBatis 是一個 XML 驅動的框架。配置信息是基于 XML 的,映射語句也是定義在 XML 中的。而在 MyBatis 3 中,我們提供了其它的配置方式。MyBatis 3 構建在全面且強大的基于 Java 語言的配置 API 之上。它是 XML 和注解配置的基礎。注解提供了一種簡單且低成本的方式來實現(xiàn)簡單的映射語句。
不幸的是,Java 注解的表達能力和靈活性十分有限。盡管我們花了很多時間在調查、設計和試驗上,但最強大的 MyBatis 映射并不能用注解來構建——我們真沒開玩笑。而 C# 屬性就沒有這些限制,因此 MyBatis.NET 的配置會比 XML 有更大的選擇余地。雖說如此,基于 Java 注解的配置還是有它的好處的。
注解如下表所示:
注解 | 使用對象 | XML 等價形式 | 描述 |
---|---|---|---|
@CacheNamespace
|
類
|
<cache>
|
為給定的命名空間(比如類)配置緩存。屬性:implemetation 、eviction 、flushInterval 、size 、readWrite 、blocking 、properties 。 |
@Property
|
N/A | <property>
|
指定參數(shù)值或占位符(placeholder)(該占位符能被 mybatis-config.xml 內的配置屬性替換)。屬性:name 、value 。(僅在 MyBatis 3.4.2 以上可用) |
@CacheNamespaceRef
|
類
|
<cacheRef>
|
引用另外一個命名空間的緩存以供使用。注意,即使共享相同的全限定類名,在 XML 映射文件中聲明的緩存仍被識別為一個獨立的命名空間。屬性:value 、name 。如果你使用了這個注解,你應設置 value 或者 name 屬性的其中一個。value 屬性用于指定能夠表示該命名空間的 Java 類型(命名空間名就是該 Java
類型的全限定類名),name 屬性(這個屬性僅在 MyBatis 3.4.2 以上可用)則直接指定了命名空間的名字。 |
@ConstructorArgs
|
方法
|
<constructor>
|
收集一組結果以傳遞給一個結果對象的構造方法。屬性:value ,它是一個 Arg 數(shù)組。 |
@Arg
|
N/A |
|
ConstructorArgs 集合的一部分,代表一個構造方法參數(shù)。屬性:id 、column 、javaType 、jdbcType 、typeHandler 、select 、resultMap 。id 屬性和 XML 元素 <idArg> 相似,它是一個布爾值,表示該屬性是否用于唯一標識和比較對象。從版本
3.5.4 開始,該注解變?yōu)榭芍貜妥⒔狻?/td>
|
@TypeDiscriminator
|
方法
|
<discriminator>
|
決定使用何種結果映射的一組取值(case)。屬性:column 、javaType 、jdbcType 、typeHandler 、cases 。cases 屬性是一個 Case 的數(shù)組。 |
@Case
|
N/A | <case>
|
表示某個值的一個取值以及該取值對應的映射。屬性:value 、type 、results 。results 屬性是一個 Results 的數(shù)組,因此這個注解實際上和 ResultMap 很相似,由下面的 Results 注解指定。 |
@Results
|
方法
|
<resultMap>
|
一組結果映射,指定了對某個特定結果列,映射到某個屬性或字段的方式。屬性:value 、id 。value 屬性是一個 Result 注解的數(shù)組。而 id 屬性則是結果映射的名稱。從版本 3.5.4 開始,該注解變?yōu)榭芍貜妥⒔狻?/td>
|
@Result
|
N/A |
|
在列和屬性或字段之間的單個結果映射。屬性:id 、column 、javaType 、jdbcType 、typeHandler 、one 、many 。id 屬性和 XML 元素 <id> 相似,它是一個布爾值,表示該屬性是否用于唯一標識和比較對象。one 屬性是一個關聯(lián),和 <association> 類似,而
many 屬性則是集合關聯(lián),和 <collection> 類似。這樣命名是為了避免產生名稱沖突。 |
@One
|
N/A | <association>
|
復雜類型的單個屬性映射。屬性: select ,指定可加載合適類型實例的映射語句(也就是映射器方法)全限定名; fetchType ,指定在該映射中覆蓋全局配置參數(shù) ?lazyLoadingEnabled ?; ?resultMap ?(從 3.5.5 開始可用),它是從選擇結果映射到單個容器對象的結果映射的完全限定名稱; ?columnPrefix ?(從 3.5.5 開始可用),它是用于分組選擇列的列前綴 嵌套結果圖。提示 注解 API 不支持聯(lián)合映射。這是由于 Java 注解不允許產生循環(huán)引用。 |
@Many
|
N/A | <collection>
|
復雜類型的集合屬性映射。屬性: select ,指定可加載合適類型實例集合的映射語句(也就是映射器方法)全限定名; fetchType ,指定在該映射中覆蓋全局配置參數(shù) lazyLoadingEnabled resultMap (從 3.5.5 開始可用),它是從選擇結果映射到集合對象的結果映射的完全限定名稱; ?columnPrefix ?(從 3.5.5 開始可用),它是用于在嵌套結果映射中對選擇列進行分組的列前綴。提示 注解 API 不支持聯(lián)合映射。這是由于 Java 注解不允許產生循環(huán)引用。 |
@MapKey
|
方法
|
供返回值為 Map 的方法使用的注解。它使用對象的某個屬性作為 key,將對象 List 轉化為 Map。屬性:value ,指定作為 Map 的 key 值的對象屬性名。 |
|
@Options
|
方法
|
映射語句的屬性 | 該注解允許你指定大部分開關和配置選項,它們通常在映射語句上作為屬性出現(xiàn)。與在注解上提供大量的屬性相比,Options 注解提供了一致、清晰的方式來指定選項。屬性:useCache=true 、flushCache=FlushCachePolicy.DEFAULT 、resultSetType=DEFAULT 、statementType=PREPARED 、fetchSize=-1 、timeout=-1 、useGeneratedKeys=false 、keyProperty="" 、keyColumn="" 、resultSets="" , databaseId="" 。注意,Java
注解無法指定 null 值。因此,一旦你使用了 Options 注解,你的語句就會被上述屬性的默認值所影響。要注意避免默認值帶來的非預期行為。 ?databaseId ?(自 3.5.5 起可用),如果配置了 ?DatabaseIdProvider ?,MyBatis 使用沒有 ?databaseId ?屬性或與當前匹配的 ?databaseId ?的選項。 如果發(fā)現(xiàn)有或沒有 ?databaseId ?,后者將被丟棄。注意: keyColumn 屬性只在某些數(shù)據庫中有效(如 Oracle、PostgreSQL 等)。要了解更多關于 keyColumn 和 keyProperty 可選值信息,請查看“insert, update 和 delete”一節(jié)。 |
|
方法
|
|
每個注解分別代表將會被執(zhí)行的 SQL 語句。它們用字符串數(shù)組(或單個字符串)作為參數(shù)。如果傳遞的是字符串數(shù)組,字符串數(shù)組會被連接成單個完整的字符串,每個字符串之間加入一個空格。這有效地避免了用 Java 代碼構建 SQL 語句時產生的“丟失空格”問題。當然,你也可以提前手動連接好字符串。屬性:value ,指定用來組成單個 SQL 語句的字符串數(shù)組。 ?databaseId ?(從 3.5.5 開始可用),如果配置了 ?DatabaseIdProvider ?,MyBatis 使用沒有 ?databaseId ?屬性或 ?databaseId ?與當前匹配的語句。 如果發(fā)現(xiàn)有或沒有 ?databaseId ?,后者將被丟棄。 |
|
方法
|
|
允許構建動態(tài) SQL。這些備選的 SQL 注解允許你指定返回 SQL 語句的類和方法,以供運行時執(zhí)行。(從 MyBatis 3.4.6 開始,可以使用 CharSequence 代替 String 來作為返回類型)。當執(zhí)行映射語句時,MyBatis 會實例化注解指定的類,并調用注解指定的方法。你可以通過 ProviderContext 傳遞映射方法接收到的參數(shù)、"Mapper
interface type" 和 "Mapper method"(僅在 MyBatis 3.4.5 以上支持)作為參數(shù)。(MyBatis 3.4 以上支持傳入多個參數(shù)) 屬性:value 、type 、method 、databaseId 。 value and type 屬性用于指定類名 (?type ?屬性是 ?value ?的別名,您必須指定其中之一。 但是當將 ?defaultSqlProviderType ?指定為全局配置時,這兩個屬性都可以省略)。 method 用于指定該類的方法名(從版本 3.5.1 開始,可以省略 method 屬性,MyBatis
將會使用 ProviderMethodResolver 接口解析方法的具體實現(xiàn)。如果解析失敗,MyBatis 將會使用名為 provideSql 的降級實現(xiàn))。提示 接下來的“SQL 語句構建器”一章將會討論該話題,以幫助你以更清晰、更便于閱讀的方式構建動態(tài) SQL。 ?databaseId ?(自 3.5.5 起可用),如果配置了 ?DatabaseIdProvider ?,MyBatis 將使用沒有 ?databaseId ?屬性或與當前匹配的 ?databaseId ?的提供程序方法。 如果發(fā)現(xiàn)有或沒有 ?databaseId ?,后者將被丟棄。 |
@Param
|
參數(shù)
|
N/A | 如果你的映射方法接受多個參數(shù),就可以使用這個注解自定義每個參數(shù)的名字。否則在默認情況下,除 RowBounds 以外的參數(shù)會以 "param" 加參數(shù)位置被命名。例如 #{param1} , #{param2} 。如果使用了 @Param("person") ,參數(shù)就會被命名為 #{person} 。 |
@SelectKey
|
方法
|
<selectKey>
|
這個注解的功能與 <selectKey> 標簽完全一致。該注解只能在 @Insert 或 @InsertProvider 或 @Update 或 @UpdateProvider 標注的方法上使用,否則將會被忽略。如果標注了 @SelectKey 注解,MyBatis
將會忽略掉由 @Options 注解所設置的生成主鍵或設置(configuration)屬性。屬性:statement 以字符串數(shù)組形式指定將會被執(zhí)行的 SQL 語句,keyProperty 指定作為參數(shù)傳入的對象對應屬性的名稱,該屬性將會更新成新的值,before 可以指定為 true 或 false 以指明
SQL 語句應被在插入語句的之前還是之后執(zhí)行。resultType 則指定 keyProperty 的 Java 類型。statementType 則用于選擇語句類型,可以選擇 STATEMENT 、PREPARED 或 CALLABLE 之一,它們分別對應于 Statement 、PreparedStatement 和 CallableStatement 。默認值是 PREPARED 。 ?databaseId ?(從 3.5.5 開始可用),如果配置了 ?DatabaseIdProvider ?,MyBatis 將使用沒有 ?databaseId ?屬性或 ?databaseId ?與當前匹配的語句。 如果發(fā)現(xiàn)有或沒有 ?databaseId ?,后者將被丟棄。 |
@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
? 注解來在插入前讀取數(shù)據庫序列的值:
@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
? 注解來在插入后讀取數(shù)據庫自增列的值:
@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(column = "cid", javaType = Integer.class, id = true),
@Arg(column = "name", javaType = String.class)
})
@Select("select * from company where id = #{id}")
Company getCompanyById(Integer id);
這個例子展示了如何使用單個參數(shù)的 ?@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();
}
}
這個例子展示了如何使用多個參數(shù)的 ?@SqlProvider
? 注解:
@SelectProvider(type = UserSqlBuilder.class, method = "buildGetUsersByName")
List<User> getUsersByName(
@Param("name") String name, @Param("orderByColumn") String orderByColumn);
class UserSqlBuilder {
// 如果不使用 @Param,就應該定義與 mapper 方法相同的參數(shù)
public static String buildGetUsersByName(
final String name, final String orderByColumn) {
return new SQL(){{
SELECT("*");
FROM("users");
WHERE("name like #{name} || '%'");
ORDER_BY(orderByColumn);
}}.toString();
}
// 如果使用 @Param,就可以只定義需要使用的參數(shù)
public static String buildGetUsersByName(@Param("orderByColumn") final String orderByColumn) {
return new SQL(){{
SELECT("*");
FROM("users");
WHERE("name like #{name} || '%'");
ORDER_BY(orderByColumn);
}}.toString();
}
}
這個例子顯示使用全局配置(自 3.5.6 起可用)將 sql 提供程序類共享給所有映射器方法的用法:
Configuration configuration = new Configuration();
configuration.setDefaultSqlProviderType(TemplateFilePathProvider.class); // Specify an sql provider class for sharing on all mapper methods
// ...
// Can omit the type/value attribute on sql provider annotation
// If omit it, the MyBatis apply the class that specified on defaultSqlProviderType.
public interface UserMapper {
@SelectProvider // Same with @SelectProvider(TemplateFilePathProvider.class)
User findUser(int id);
@InsertProvider // Same with @InsertProvider(TemplateFilePathProvider.class)
void createUser(User user);
@UpdateProvider // Same with @UpdateProvider(TemplateFilePathProvider.class)
void updateUser(User user);
@DeleteProvider // Same with @DeleteProvider(TemplateFilePathProvider.class)
void deleteUser(int id);
}
以下例子展示了 ?ProviderMethodResolver
?(3.5.1 后可用)的默認實現(xiàn)使用方法:
@SelectProvider(UserSqlProvider.class)
List<User> getUsersByName(String name);
// 在你的 provider 類中實現(xiàn) ProviderMethodResolver 接口
class UserSqlProvider implements ProviderMethodResolver {
// 默認實現(xiàn)中,會將映射器方法的調用解析到實現(xiàn)的同名方法上
public static String getUsersByName(final String name) {
return new SQL(){{
SELECT("*");
FROM("users");
if (name != null) {
WHERE("name like #{value} || '%'");
}
ORDER_BY("id");
}}.toString();
}
}
這個例子顯示語句注釋上的 ?databaseId
?屬性的用法(自 3.5.5 起可用):
@Select(value = "SELECT SYS_GUID() FROM dual", databaseId = "oracle") // Use this statement if DatabaseIdProvider provide "oracle"
@Select(value = "SELECT uuid_generate_v4()", databaseId = "postgres") // Use this statement if DatabaseIdProvider provide "postgres"
@Select("SELECT RANDOM_UUID()") // Use this statement if the DatabaseIdProvider not configured or not matches databaseId
String generateId();
更多建議: