十年網(wǎng)站開發(fā)經(jīng)驗(yàn) + 多家企業(yè)客戶 + 靠譜的建站團(tuán)隊(duì)
量身定制 + 運(yùn)營維護(hù)+專業(yè)推廣+無憂售后,網(wǎng)站問題一站解決
正如之前所提到的,?SqlSession ?在 Mybatis 中是非常強(qiáng)大的一個(gè)類。它包含了所有執(zhí)行語句、提交或回滾事務(wù)以及獲取映射器實(shí)例的方法。

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