ibatis中list做回參很簡單,resultClass設為list中元素類型,dao層調用:
(List)getSqlMapClientTemplate().queryForList("sqlName", paraName);
並經類型轉換即可,做入參還需要稍微調整下,本文主要講list做入參碰到的幾個小問題:
入參主要有兩種方法一種是以list直接作為入參,另一種是將list作為map的元素之一為入參,個人覺得第一種明顯優勢,就一個list為入參,還用map包裝一層多蛋疼。下面的介紹都以這個sql為例
"getProjectJobIdsByProjectIds" resultClass="java.lang.Integer" parameterClass="java.util.ArrayList"> SELECT id FROM cic_job WHERE last_buildid <> 'NULL' "AND" open="(" close=")" conjunction="or"> CRID=#projectIdList[]#
以上是正確的寫法,意義大家不用關注,重點放在倒數2到4行,表示以list為入參,其中projectIdList為dao層傳入的參數名。主要寫法就是parameterClass="java.util.ArrayList",然后加上
"AND" open="(" close=")" conjunction="or">
CRID=#projectIdList[]#
意思就是迭代器循環projectIdList,並用or拼接形成sql,拼接完后用()括起來,在加上前綴and。
1、iterate property的問題
網上很多寫法是:
property="projectIdList" prepend="AND" open="(" close=")" conjunction="or">
即多了一個property,這個時候ibatis會從參數中尋找屬性為projectIdList的對象,而list是一個對象沒有屬性就會報錯:
Cause: com.ibatis.common.beans.ProbeException: Error getting ordinal list from JavaBean.
Cause java.lang.StringIndexOutOfBoundsException: String index out of range: -1
異常,解決方法就是去掉property="projectIdList"
其實這種寫法是相對第二種以map為參數而言的,你可以使用map傳入參數設置屬性為 property對應名即可。
2、< ! [ CDATA[的問題
大家注意到上面sql添加有 ! [ CDATA[,它的作用是對一些字符進行轉移,具體可以參見http://renren.it/a/JAVAbiancheng/iBATIS/20111105/139874.html
但上面sql如果寫成:
<select id="getProjectJobIdsByProjectIds" resultClass="java.lang.Integer" parameterClass="java.util.ArrayList"> <![CDATA[ SELECT id FROM cic_job WHERE last_buildid <> 'NULL' <iterate prepend="AND" open="(" close=")" conjunction="or"> CRID=#projectIdList[]# </iterate> ]]> </select>
擴大轉義范圍會出現如下錯誤:
com.ibatis.common.beans.ProbeException: There is no READABLE property named 'projectIdList[]' in class 'java.util.ArrayList'
解決方法,就是縮小 CDATA的范圍。原因是CDATA導致系統無法識別動態判斷部分。
在使用ibatis時,經常需要配置待執行的sql語句。使用過ibatis的朋友都知道,無可避免的都會碰到一些不兼容、沖突的字符,多數人也都 知道用<![CDATA[ ]]>標記避免Sql中與xml規范相沖突的字符對xml映射文件的合法性造成影響。但是,如果在ibatis中使用了動態語句的時候,還是有一些 細節需要注意。下面舉例說明一下:
環境:oracle、ibatis、java
錯誤例1:符號“<=”會對xml映射文件的合法性造成影響
<select id="find" parameterClass="java.util.Map" resultClass="java.lang.Long"> select id from tableA a, tableB b <dynamic prepend="WHERE"> <isNotNull prepend="AND" property="startDate"> a.act_time >= #startDate# and a.act_time <= #endDate# and a.id = b.id </isNotNull> </dynamic> </select>
錯誤例2:將整個sql語句用<![CDATA[ ]]>標記來避免沖突,在一般情況下都是可行的,但是由於該sql配置中有動態語句(where部分),將導致系統無法識別動態判斷部分,導致整個sql語句非法。
<select id="find" parameterClass="java.util.Map" resultClass="java.lang.Long"> < ![CDATA[ select id from tableA a, tableB b <dynamic prepend="WHERE"> <isNotNull prepend="AND" property="startDate"> a.act_time >= #startDate# and a.act_time <= #endDate# and a.id = b.id </isNotNull> </dynamic> ]]> </select>
正確做法:縮小范圍,只對有字符沖突部分進行合法性調整。
<select id="find" parameterClass="java.util.Map" resultClass="java.lang.Long"> select id from tableA a, tableB b <dynamic prepend="WHERE"> <isNotNull prepend="AND" property="startDate"> a.act_time >= #startDate# < ![CDATA[ and a.act_time <= #endDate# ]]> and a.id = b.id </isNotNull> </dynamic> </select>
ibatis中應該經常見到"<![CDATA["這樣的東西吧,它的用處應該是轉義一些特殊關鍵字字符,不合法的XML字符必須被替換為相應的實體。 下面是五個在XML文檔中預定義好的實體:
< | > | 小於號 |
> | < | 大於號 |
& | & | 和 |
' | ' | 單引號 |
" | " | 雙引號 |
一個 CDATA 部件以"< ! [CDATA[" 標記開始,以"]]>"標記結束:
<message>if salary < 1000 then</message> |
為了避免出現這種情況,必須將字符"<" 轉換成實體,象下面這樣:
<message>if salary < 1000 then</message> |
這里有一個問題,由於我在ibatis中用到了一個循環標簽"<iterate>" ,為了寫一個 類似
SELECT * FROM b
WHERE b.trade_no in
<iterate property="tradeNoList" open="(" close=")" conjunction=",">#tradeNoList[]#</iterate>
AND .........這樣的一個語句。
由於"<iterate"標簽以 "<"開頭,那么可能被"< ! [CDATA["轉義了,所以造成語法錯誤,sql不能正常執行,去掉"<![CDATA["后發現sql能正常執行。
所以在碰到類似問題的時候,應該留意,在"< ! [CDATA["轉義符中間不要用標簽。