MyBatis中XML 映射文件中常見的標(biāo)簽說明
SQL 映射文件只有很少的幾個頂級元素(按照應(yīng)被定義的順序列出):
- cache – 對給定命名空間的緩存配置。
- cache-ref – 對其他命名空間緩存配置的引用。
- resultMap – 是最復(fù)雜也是最強(qiáng)大的元素,用來描述如何從數(shù)據(jù)庫結(jié)果集中來加載對象。
- parameterMap – 已被廢棄!老式風(fēng)格的參數(shù)映射。更好的辦法是使用內(nèi)聯(lián)參數(shù),此元素可能在將來被移除。
- sql – 可被其他語句引用的可重用語句塊。
- insert – 映射插入語句
- update – 映射更新語句
- delete – 映射刪除語句
- select – 映射查詢語句
select
<select id="selectPerson" parameterType="int" resultType="hashmap">
SELECT * FROM PERSON WHERE ID = #{id}
</select>
這個語句被稱作 selectPerson,接受一個 int(或 Integer)類型的參數(shù),并返回一個 HashMap 類型的對象,其中的鍵是列名,值便是結(jié)果行中的對應(yīng)值。
注意參數(shù)符號:#{id}
這就告訴 MyBatis 創(chuàng)建一個預(yù)處理語句(PreparedStatement)參數(shù),在 JDBC 中,這樣的一個參數(shù)在 SQL 中會由一個“?”來標(biāo)識,并被傳遞到一個新的預(yù)處理語句中,就像這樣:
// 近似的 JDBC 代碼,非 MyBatis 代碼... String selectPerson = "SELECT * FROM PERSON WHERE ID=?"; PreparedStatement ps = conn.prepareStatement(selectPerson); ps.setInt(1,id); <select id="selectPerson" parameterType="int" parameterMap="deprecated" resultType="hashmap" resultMap="personResultMap" flushCache="false" useCache="true" timeout="10" fetchSize="256" statementType="PREPARED" resultSetType="FORWARD_ONLY">
| 屬性 | 描述 |
|---|---|
| id | 在命名空間中唯一的標(biāo)識符,可以被用來引用這條語句。 |
| parameterType | 將會傳入這條語句的參數(shù)類的完全限定名或別名。這個屬性是可選的,因?yàn)?MyBatis 可以通過類型處理器(TypeHandler) 推斷出具體傳入語句的參數(shù),默認(rèn)值為未設(shè)置(unset)。 |
| parameterMap | 這是引用外部 parameterMap 的已經(jīng)被廢棄的方法。請使用內(nèi)聯(lián)參數(shù)映射和 parameterType 屬性。 |
| resultType | 從這條語句中返回的期望類型的類的完全限定名或別名。 注意如果返回的是集合,那應(yīng)該設(shè)置為集合包含的類型,而不是集合本身。可以使用 resultType 或 resultMap,但不能同時使用。 |
| resultMap | 外部 resultMap 的命名引用。結(jié)果集的映射是 MyBatis 最強(qiáng)大的特性,如果你對其理解透徹,許多復(fù)雜映射的情形都能迎刃而解??梢允褂?resultMap 或 resultType,但不能同時使用。 |
| flushCache | 將其設(shè)置為 true 后,只要語句被調(diào)用,都會導(dǎo)致本地緩存和二級緩存被清空,默認(rèn)值:false。 |
| useCache | 將其設(shè)置為 true 后,將會導(dǎo)致本條語句的結(jié)果被二級緩存緩存起來,默認(rèn)值:對 select 元素為 true。 |
| timeout | 這個設(shè)置是在拋出異常之前,驅(qū)動程序等待數(shù)據(jù)庫返回請求結(jié)果的秒數(shù)。默認(rèn)值為未設(shè)置(unset)(依賴驅(qū)動)。 |
| fetchSize | 這是一個給驅(qū)動的提示,嘗試讓驅(qū)動程序每次批量返回的結(jié)果行數(shù)和這個設(shè)置值相等。 默認(rèn)值為未設(shè)置(unset)(依賴驅(qū)動)。 |
| statementType | STATEMENT,PREPARED 或 CALLABLE 中的一個。這會讓 MyBatis 分別使用 Statement,PreparedStatement 或 CallableStatement,默認(rèn)值:PREPARED。 |
| resultSetType | FORWARD_ONLY,SCROLL_SENSITIVE, SCROLL_INSENSITIVE 或 DEFAULT(等價于 unset) 中的一個,默認(rèn)值為 unset (依賴驅(qū)動)。 |
| databaseId | 如果配置了數(shù)據(jù)庫廠商標(biāo)識(databaseIdProvider),MyBatis 會加載所有的不帶 databaseId 或匹配當(dāng)前 databaseId 的語句;如果帶或者不帶的語句都有,則不帶的會被忽略。 |
| resultOrdered | 這個設(shè)置僅針對嵌套結(jié)果 select 語句適用:如果為 true,就是假設(shè)包含了嵌套結(jié)果集或是分組,這樣的話當(dāng)返回一個主結(jié)果行的時候,就不會發(fā)生有對前面結(jié)果集的引用的情況。 這就使得在獲取嵌套的結(jié)果集的時候不至于導(dǎo)致內(nèi)存不夠用。默認(rèn)值:false。 |
| resultSets | 這個設(shè)置僅對多結(jié)果集的情況適用。它將列出語句執(zhí)行后返回的結(jié)果集并給每個結(jié)果集一個名稱,名稱是逗號分隔的。 |
insert, update 和 delete
數(shù)據(jù)變更語句 insert,update 和 delete 的實(shí)現(xiàn)非常接近:
<insert id="insertAuthor" parameterType="domain.blog.Author" flushCache="true" statementType="PREPARED" keyProperty="" keyColumn="" useGeneratedKeys="" timeout="20"> <update id="updateAuthor" parameterType="domain.blog.Author" flushCache="true" statementType="PREPARED" timeout="20"> <delete id="deleteAuthor" parameterType="domain.blog.Author" flushCache="true" statementType="PREPARED" timeout="20">
| 屬性 | 描述 |
|---|---|
| id | 命名空間中的唯一標(biāo)識符,可被用來代表這條語句。 |
| parameterType | 將要傳入語句的參數(shù)的完全限定類名或別名。這個屬性是可選的,因?yàn)?MyBatis 可以通過類型處理器推斷出具體傳入語句的參數(shù),默認(rèn)值為未設(shè)置(unset)。 |
| parameterMap | 這是引用外部 parameterMap 的已經(jīng)被廢棄的方法。請使用內(nèi)聯(lián)參數(shù)映射和 parameterType 屬性。 |
| flushCache | 將其設(shè)置為 true 后,只要語句被調(diào)用,都會導(dǎo)致本地緩存和二級緩存被清空,默認(rèn)值:true(對于 insert、update 和 delete 語句)。 |
| timeout | 這個設(shè)置是在拋出異常之前,驅(qū)動程序等待數(shù)據(jù)庫返回請求結(jié)果的秒數(shù)。默認(rèn)值為未設(shè)置(unset)(依賴驅(qū)動)。 |
| statementType | STATEMENT,PREPARED 或 CALLABLE 的一個。這會讓 MyBatis 分別使用 Statement,PreparedStatement 或 CallableStatement,默認(rèn)值:PREPARED。 |
| useGeneratedKeys | (僅對 insert 和 update 有用)這會令 MyBatis 使用 JDBC 的 getGeneratedKeys 方法來取出由數(shù)據(jù)庫內(nèi)部生成的主鍵(比如:像 MySQL 和 SQL Server 這樣的關(guān)系數(shù)據(jù)庫管理系統(tǒng)的自動遞增字段),默認(rèn)值:false。 |
| keyProperty | (僅對 insert 和 update 有用)唯一標(biāo)記一個屬性,MyBatis 會通過 getGeneratedKeys 的返回值或者通過 insert 語句的 selectKey 子元素設(shè)置它的鍵值,默認(rèn)值:未設(shè)置(unset)。如果希望得到多個生成的列,也可以是逗號分隔的屬性名稱列表。 |
| keyColumn | (僅對 insert 和 update 有用)通過生成的鍵值設(shè)置表中的列名,這個設(shè)置僅在某些數(shù)據(jù)庫(像 PostgreSQL)是必須的,當(dāng)主鍵列不是表中的第一列的時候需要設(shè)置。如果希望使用多個生成的列,也可以設(shè)置為逗號分隔的屬性名稱列表。 |
| databaseId | 如果配置了數(shù)據(jù)庫廠商標(biāo)識(databaseIdProvider),MyBatis 會加載所有的不帶 databaseId 或匹配當(dāng)前 databaseId 的語句;如果帶或者不帶的語句都有,則不帶的會被忽略。 |
生成主鍵
<selectKey keyProperty="id" resultType="int" order="BEFORE" statementType="PREPARED">
| 屬性 | 描述 |
|---|---|
| keyProperty | selectKey 語句結(jié)果應(yīng)該被設(shè)置的目標(biāo)屬性。如果希望得到多個生成的列,也可以是逗號分隔的屬性名稱列表。 |
| keyColumn | 匹配屬性的返回結(jié)果集中的列名稱。如果希望得到多個生成的列,也可以是逗號分隔的屬性名稱列表。 |
| resultType | 結(jié)果的類型。MyBatis 通??梢酝茢喑鰜恚菫榱烁泳_,寫上也不會有什么問題。MyBatis 允許將任何簡單類型用作主鍵的類型,包括字符串。如果希望作用于多個生成的列,則可以使用一個包含期望屬性的 Object 或一個 Map。 |
| order | 這可以被設(shè)置為 BEFORE 或 AFTER。如果設(shè)置為 BEFORE,那么它會首先生成主鍵,設(shè)置 keyProperty 然后執(zhí)行插入語句。如果設(shè)置為 AFTER,那么先執(zhí)行插入語句,然后是 selectKey 中的語句 - 這和 Oracle 數(shù)據(jù)庫的行為相似,在插入語句內(nèi)部可能有嵌入索引調(diào)用。 |
| statementType | 與前面相同,MyBatis 支持 STATEMENT,PREPARED 和 CALLABLE 語句的映射類型,分別代表 PreparedStatement 和 CallableStatement 類型。 |
<selectKey resultType="java.lang.Long" order="AFTER" keyProperty="id"> SELECT LAST_INSERT_ID() AS id </selectKey>
sql
這個元素可以被用來定義可重用的 SQL 代碼段,這些 SQL 代碼可以被包含在其他語句中。它可以(在加載的時候)被靜態(tài)地設(shè)置參數(shù)。 在不同的包含語句中可以設(shè)置不同的值到參數(shù)占位符上。比如:
<sql id="userColumns"> ${alias}.id,${alias}.username,${alias}.password </sql>
<select id="selectUsers" resultType="map">
select
<include refid="userColumns"><property name="alias" value="t1"/></include>,
<include refid="userColumns"><property name="alias" value="t2"/></include>
from some_table t1
cross join some_table t2
</select>
結(jié)果映射
resultMap 元素是 MyBatis 中最重要最強(qiáng)大的元素,在一些情形下允許你進(jìn)行一些 JDBC 不支持的操作。實(shí)際上,在為一些比如連接的復(fù)雜語句編寫映射代碼的時候,一份 resultMap 能夠代替實(shí)現(xiàn)同等功能的長達(dá)數(shù)千行的代碼。ResultMap 的設(shè)計(jì)思想是,對于簡單的語句根本不需要配置顯式的結(jié)果映射,而對于復(fù)雜一點(diǎn)的語句只需要描述它們的關(guān)系就行了。
在JavaBean中定義一個有 3 個屬性:id,username 和 hashedPassword的類,然后在mapper.xml中,這些屬性會對應(yīng)到 select 語句中的列名,這樣的一個 JavaBean 可以被映射到 ResultSet,就像映射到 HashMap 一樣簡單。
<select id="selectUsers" resultType="com.someapp.model.User">
select id, username, hashedPassword
from some_table
where id = #{id}
</select>
像第三中的第三個例子,也可以定義外部resultMap,這也是解決列名不匹配的另外一種方式。
<resultMap id="userResultMap" type="User">
<id property="id" column="user_id" />
<result property="username" column="user_name"/>
<result property="password" column="hashed_password"/>
</resultMap>
<select id="selectUsers" resultMap="userResultMap">
select user_id, user_name, hashed_password
from some_table
where id = #{id}
</select>
結(jié)果映射(resultMap)
- constructor-用于在實(shí)例化類時,注入結(jié)果到構(gòu)造方法中
- idArg - ID 參數(shù);標(biāo)記出作為 ID 的結(jié)果可以幫助提高整體性能
- arg - 將被注入到構(gòu)造方法的一個普通結(jié)果
- id – 一個 ID 結(jié)果;標(biāo)記出作為 ID 的結(jié)果可以幫助提高整體性能
- result – 注入到字段或 JavaBean 屬性的普通結(jié)果
- association– 一個復(fù)雜類型的關(guān)聯(lián);許多結(jié)果將包裝成這種類型
- 嵌套結(jié)果映射 – 關(guān)聯(lián)本身可以是一個 resultMap 元素,或者從別處引用一個
- collection– 一個復(fù)雜類型的集合
- 嵌套結(jié)果映射 – 集合本身可以是一個 resultMap 元素,或者從別處引用一個
- discriminator– 使用結(jié)果值來決定使用哪個resultMap
- case– 基于某些值的結(jié)果映射
- 嵌套結(jié)果映射 – case 本身可以是一個 resultMap 元素,因此可以具有相同的結(jié)構(gòu)和元素,或者從別處引用一個。
| 屬性 | 描述 |
|---|---|
| id | 當(dāng)前命名空間中的一個唯一標(biāo)識,用于標(biāo)識一個結(jié)果映射。 |
| type | 類的完全限定名, 或者一個類型別名(關(guān)于內(nèi)置的類型別名,可以參考上面的表格)。 |
| autoMapping | 如果設(shè)置這個屬性,MyBatis將會為本結(jié)果映射開啟或者關(guān)閉自動映射。 這個屬性會覆蓋全局的屬性 autoMappingBehavior。默認(rèn)值:未設(shè)置(unset)。 |
id & result
<id property="id" column="post_id"/> <result property="subject" column="post_subject"/>
這些是結(jié)果映射最基本的內(nèi)容。id 和 result 元素都將一個列的值映射到一個簡單數(shù)據(jù)類型(String, int, double, Date 等)的屬性或字段。
這兩者之間的唯一不同是,id 元素表示的結(jié)果將是對象的標(biāo)識屬性,這會在比較對象實(shí)例時用到。 這樣可以提高整體的性能,尤其是進(jìn)行緩存和嵌套結(jié)果映射(也就是連接映射)的時候。
| 屬性 | 描述 |
|---|---|
| property | 映射到列結(jié)果的字段或?qū)傩?。如果用來匹配?JavaBean 存在給定名字的屬性,那么它將會被使用。否則 MyBatis 將會尋找給定名稱的字段。 無論是哪一種情形,你都可以使用通常的點(diǎn)式分隔形式進(jìn)行復(fù)雜屬性導(dǎo)航。 比如,你可以這樣映射一些簡單的東西:“username”,或者映射到一些復(fù)雜的東西上:“address.street.number”。 |
| column | 數(shù)據(jù)庫中的列名,或者是列的別名。一般情況下,這和傳遞給 resultSet.getString(columnName) 方法的參數(shù)一樣。 |
| javaType | 一個 Java 類的完全限定名,或一個類型別名(關(guān)于內(nèi)置的類型別名,可以參考上面的表格)。 如果你映射到一個 JavaBean,MyBatis 通常可以推斷類型。然而,如果你映射到的是 HashMap,那么你應(yīng)該明確地指定 javaType 來保證行為與期望的相一致。 |
| jdbcType | JDBC 類型,所支持的 JDBC 類型參見這個表格之后的“支持的 JDBC 類型”。 只需要在可能執(zhí)行插入、更新和刪除的且允許空值的列上指定 JDBC 類型。這是 JDBC 的要求而非 MyBatis 的要求。如果你直接面向 JDBC 編程,你需要對可能存在空值的列指定這個類型。 |
| typeHandler | 我們在前面討論過默認(rèn)的類型處理器。使用這個屬性,你可以覆蓋默認(rèn)的類型處理器。 這個屬性值是一個類型處理器實(shí)現(xiàn)類的完全限定名,或者是類型別名。 |
緩存
默認(rèn)情況下,只啟用了本地的會話緩存,它僅僅對一個會話中的數(shù)據(jù)進(jìn)行緩存。 要啟用全局的二級緩存,只需要在你的 SQL 映射文件中添加一行:<cache/>
基本上就是這樣。這個簡單語句的效果如下:
- 映射語句文件中的所有 select 語句的結(jié)果將會被緩存。
- 映射語句文件中的所有 insert、update 和 delete 語句會刷新緩存。
- 緩存會使用最近最少使用算法(LRU, Least Recently Used)算法來清除不需要的緩存。
- 緩存不會定時進(jìn)行刷新(也就是說,沒有刷新間隔)。
- 緩存會保存列表或?qū)ο螅o論查詢方法返回哪種)的 1024 個引用。
- 緩存會被視為讀/寫緩存,這意味著獲取到的對象并不是共享的,可以安全地被調(diào)用者修改,而不干擾其他調(diào)用者或線程所做的潛在修改。
提示 緩存只作用于 cache 標(biāo)簽所在的映射文件中的語句。如果你混合使用 Java API 和 XML 映射文件,在共用接口中的語句將不會被默認(rèn)緩存。你需要使用 @CacheNamespaceRef 注解指定緩存作用域。
這些屬性可以通過 cache 元素的屬性來修改。比如:
<cache eviction="FIFO" flushInterval="60000" size="512" readOnly="true"/>
這個更高級的配置創(chuàng)建了一個 FIFO 緩存,每隔 60 秒刷新,最多可以存儲結(jié)果對象或列表的 512 個引用,而且返回的對象被認(rèn)為是只讀的,因此對它們進(jìn)行修改可能會在不同線程中的調(diào)用者產(chǎn)生沖突。
可用的清除策略有:
- LRU – 最近最少使用:移除最長時間不被使用的對象。
- FIFO – 先進(jìn)先出:按對象進(jìn)入緩存的順序來移除它們。
- SOFT – 軟引用:基于垃圾回收器狀態(tài)和軟引用規(guī)則移除對象。
- WEAK – 弱引用:更積極地基于垃圾收集器狀態(tài)和弱引用規(guī)則移除對象。
默認(rèn)的清除策略是 LRU。
flushInterval(刷新間隔)屬性可以被設(shè)置為任意的正整數(shù),設(shè)置的值應(yīng)該是一個以毫秒為單位的合理時間量。 默認(rèn)情況是不設(shè)置,也就是沒有刷新間隔,緩存僅僅會在調(diào)用語句時刷新。
size(引用數(shù)目)屬性可以被設(shè)置為任意正整數(shù),要注意欲緩存對象的大小和運(yùn)行環(huán)境中可用的內(nèi)存資源。默認(rèn)值是 1024。
readOnly(只讀)屬性可以被設(shè)置為 true 或 false。只讀的緩存會給所有調(diào)用者返回緩存對象的相同實(shí)例。 因此這些對象不能被修改。這就提供了可觀的性能提升。而可讀寫的緩存會(通過序列化)返回緩存對象的拷貝。 速度上會慢一些,但是更安全,因此默認(rèn)值是 false。
提示 二級緩存是事務(wù)性的。這意味著,當(dāng) SqlSession 完成并提交時,或是完成并回滾,但沒有執(zhí)行 flushCache=true 的 insert/delete/update 語句時,緩存會獲得更新。
使用自定義緩存
除了上述自定義緩存的方式,你也可以通過實(shí)現(xiàn)你自己的緩存,或?yàn)槠渌谌骄彺娣桨竸?chuàng)建適配器,來完全覆蓋緩存行為。
<cache type="com.domain.something.MyCustomCache"/>
例子:
type 屬性指定的類必須實(shí)現(xiàn) org.mybatis.cache.Cache 接口,且提供一個接受 String 參數(shù)作為 id 的構(gòu)造器。 這個接口是 MyBatis 框架中許多復(fù)雜的接口之一,但是行為卻非常簡單。
public interface Cache {
String getId();
int getSize();
void putObject(Object key, Object value);
Object getObject(Object key);
boolean hasKey(Object key);
Object removeObject(Object key);
void clear();
}
動態(tài)SQL
- Mybatis 動態(tài) SQL ,可以讓我們在 XML 映射文件內(nèi),以 XML 標(biāo)簽的形式編寫動態(tài) SQL ,完成邏輯判斷和動態(tài)拼接 SQL 的功能。
- Mybatis 提供了 9 種動態(tài) SQL 標(biāo)簽:<if />、<choose />、<when />、<otherwise />、<trim />、<where />、<set />、<foreach />、<bind /> 。
- 其執(zhí)行原理為,使用 OGNL 的表達(dá)式,從 SQL 參數(shù)對象中計(jì)算表達(dá)式的值,根據(jù)表達(dá)式的值動態(tài)拼接 SQL ,以此來完成動態(tài) SQL 的功能。
if
動態(tài) SQL 通常要做的事情是根據(jù)條件包含 where 子句的一部分。比如:
<select id="findActiveBlogWithTitleLike"
resultType="Blog">
SELECT * FROM BLOG
WHERE state = ‘ACTIVE'
<if test="title != null">
AND title like #{title}
</if>
</select>
這條語句提供了一種可選的查找文本功能。如果沒有傳入“title”,那么所有處于“ACTIVE”狀態(tài)的BLOG都會返回;反之若傳入了“title”,那么就會對“title”一列進(jìn)行模糊查找并返回 BLOG 結(jié)果(“title”參數(shù)值是可以包含一些掩碼或通配符的)。
通過“title”和“author”兩個參數(shù)進(jìn)行可選搜索:
<select id="findActiveBlogLike"
resultType="Blog">
SELECT * FROM BLOG WHERE state = ‘ACTIVE'
<if test="title != null">
AND title like #{title}
</if>
<if test="author != null and author.name != null">
AND author_name like #{author.name}
</if>
</select>
choose, when, otherwise
有時我們不想應(yīng)用到所有的條件語句,而只想從中擇其一項(xiàng)。針對這種情況,MyBatis 提供了 choose 元素,它有點(diǎn)像 Java 中的 switch 語句。
這次變?yōu)樘峁┝恕皌itle”就按“title”查找,提供了“author”就按“author”查找的情形,若兩者都沒有提供,就返回所有符合條件的 BLOG(實(shí)際情況可能是由管理員按一定策略選出 BLOG 列表,而不是返回大量無意義的隨機(jī)結(jié)果)。
<select id="findActiveBlogLike"
resultType="Blog">
SELECT * FROM BLOG WHERE state = ‘ACTIVE'
<choose>
<when test="title != null">
AND title like #{title}
</when>
<when test="author != null and author.name != null">
AND author_name like #{author.name}
</when>
<otherwise>
AND featured = 1
</otherwise>
</choose>
</select>
trim, where, set
上面的幾個例子,如果條件不滿足的話,會拼湊成不成一條sql語句,導(dǎo)致無法查詢,如:SELECT * FROM BLOG WHERE
<select id="findActiveBlogLike"
resultType="Blog">
SELECT * FROM BLOG
<where>
<if test="state != null">
state = #{state}
</if>
<if test="title != null">
AND title like #{title}
</if>
<if test="author != null and author.name != null">
AND author_name like #{author.name}
</if>
</where>
</select>
where 元素只會在至少有一個子元素的條件返回 SQL 子句的情況下才去插入“WHERE”子句。而且,若語句的開頭為“AND”或“OR”,where 元素也會將它們?nèi)コ?/p>
如果 where 元素沒有按正常套路出牌,我們可以通過自定義 trim 元素來定制 where 元素的功能。比如,和 where 元素等價的自定義 trim 元素為:
<trim prefix="WHERE" prefixOverrides="AND |OR "> ... </trim>
prefixOverrides 屬性會忽略通過管道分隔的文本序列(注意此例中的空格也是必要的)。它的作用是移除所有指定在 prefixOverrides 屬性中的內(nèi)容,并且插入 prefix 屬性中指定的內(nèi)容。
類似的用于動態(tài)更新語句的解決方案叫做 set。set 元素可以用于動態(tài)包含需要更新的列,而舍去其它的。比如:
<update id="updateAuthorIfNecessary">
update Author
<set>
<if test="username != null">username=#{username},</if>
<if test="password != null">password=#{password},</if>
<if test="email != null">email=#{email},</if>
<if test="bio != null">bio=#{bio}</if>
</set>
where id=#{id}
</update>
這里,set 元素會動態(tài)前置 SET 關(guān)鍵字,同時也會刪掉無關(guān)的逗號,因?yàn)橛昧藯l件語句之后很可能就會在生成的 SQL 語句的后面留下這些逗號。(譯者注:因?yàn)橛玫氖恰癷f”元素,若最后一個“if”沒有匹配上而前面的匹配上,SQL 語句的最后就會有一個逗號遺留)
若你對 set 元素等價的自定義 trim 元素的代碼感興趣,那這就是它的真面目:
<trim prefix="SET" suffixOverrides=","> ... </trim>
注意這里我們刪去的是后綴值,同時添加了前綴值。
foreach
動態(tài) SQL 的另外一個常用的操作需求是對一個集合進(jìn)行遍歷,通常是在構(gòu)建 IN 條件語句的時候。比如:
<select id="selectPostIn" resultType="domain.blog.Post">
SELECT *
FROM POST P
WHERE ID in
<foreach item="item" index="index" collection="list"
open="(" separator="," close=")">
#{item}
</foreach>
</select>
foreach 元素的功能非常強(qiáng)大,它允許你指定一個集合,聲明可以在元素體內(nèi)使用的集合項(xiàng)(item)和索引(index)變量。它也允許你指定開頭與結(jié)尾的字符串以及在迭代結(jié)果之間放置分隔符。這個元素是很智能的,因此它不會偶然地附加多余的分隔符。
注意
可以將任何可迭代對象(如 List、Set 等)、Map 對象或者數(shù)組對象傳遞給 foreach 作為集合參數(shù)。當(dāng)使用可迭代對象或者數(shù)組時,index 是當(dāng)前迭代的次數(shù),item 的值是本次迭代獲取的元素。當(dāng)使用 Map 對象(或者 Map.Entry 對象的集合)時,index 是鍵,item 是值。
bind
bind 元素可以從 OGNL 表達(dá)式中創(chuàng)建一個變量并將其綁定到上下文。比如:
<select id="selectBlogsLike" resultType="Blog">
<bind name="pattern" value="'%' + _parameter.getTitle() + '%'" />
SELECT * FROM BLOG
WHERE title LIKE #{pattern}
</select>
以上為個人經(jīng)驗(yàn),希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
解決啟用 Spring-Cloud-OpenFeign 配置可刷新項(xiàng)目無法啟動的問題
這篇文章主要介紹了解決啟用 Spring-Cloud-OpenFeign 配置可刷新項(xiàng)目無法啟動的問題,本文重點(diǎn)給大家介紹Spring-Cloud-OpenFeign的原理及問題解決方法,需要的朋友可以參考下2021-10-10
Spring的@PreAuthorize注解自定義權(quán)限校驗(yàn)詳解
這篇文章主要介紹了Spring的@PreAuthorize注解自定義權(quán)限校驗(yàn)詳解,由于項(xiàng)目中,需要對外開放接口,要求做請求頭校驗(yàn),不做其他權(quán)限控制,所以準(zhǔn)備對開放的接口全部放行,不做登錄校驗(yàn),需要的朋友可以參考下2023-11-11
使用Eclipse開發(fā)工具如何解決Java Compiler中Annotation Processin不出現(xiàn)的問題
這篇文章主要介紹了使用Eclipse開發(fā)工具如何解決Java Compiler中Annotation Processin不出現(xiàn)的相關(guān)資料,需要的朋友可以參考下2015-11-11
Java實(shí)現(xiàn)樹形結(jié)構(gòu)的示例代碼
由于業(yè)務(wù)需要,后端需要返回一個樹型結(jié)構(gòu)給前端,包含父子節(jié)點(diǎn)的數(shù)據(jù)已經(jīng)在數(shù)據(jù)庫中存儲好。本文將為大家分享Java現(xiàn)樹形結(jié)構(gòu)的示例代碼,需要的可以參考下2022-05-05
淺談Java?abstract關(guān)鍵字不能和哪些關(guān)鍵字共存
本文主要介紹了Java?abstract關(guān)鍵字不能和哪些關(guān)鍵字共存,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-10-10
java優(yōu)化hibernate性能的幾點(diǎn)建議
以上是在進(jìn)行struts+hibernate+spring進(jìn)行項(xiàng)目開發(fā)中,對hibernate性能優(yōu)化的幾點(diǎn)心得。2008-10-10

