ibatis 中動態SQL查詢和動態標籤嵌套的使用

ibatis 動態查詢
對於從事 Java EE 的開發人員來講,iBatis 是一個再熟悉不過的持久層框架了,在 Hibernate、JPA 這樣的一站式對象 / 關係映射(O/R Mapping)解決方案盛行以前,iBaits 基本是持久層框架的不二選擇。即便在持久層框架層出不窮的今天,iBatis 憑藉着易學易用、輕巧靈活等特色,也仍然擁有一席之地。尤爲對於擅長 SQL 的開發人員來講,iBatis 對 SQL 和存儲過程的直接支持可以讓他們在得到 iBatis 封裝優點的同時而不喪失 SQL 調優的手段,這是 Hibernate/JPA 所沒法比擬的。若要了解、學習ibatis,請看 iBatis開發環境搭建和示例 。java

在項目開發的過程當中,確定會遇到須要根據需求動態組裝sql 語句的時候,這時,ibatis的動態查詢功能應運而生。sql

    使用動態查詢是iBatis一個很是強大的功能。有時你已經改變WHERE子句條件的基礎上你的參數對象的狀態。在這種狀況下的iBATIS提供了一組能夠映射語句中使用,以提升SQL語句的重用性和靈活性的動態SQL標籤。動態標籤的做用是動態構建SQL語句,根據不一樣的一元或二元運算條件構建複雜的SQL語句,這功能很是好,這樣就能夠把寫的BO層的SQL語句構造移值到SQL MAP 文件裏。例如: 數據庫

select id="findUser" resultClass="User">
SELECT * User
<dynamic prepend="WHERE ">
<isNull property="id">
id IS NULL
</isNull>
<isNotNull property="id">
id = #id#
</isNotNull>
</dynamic>
</select>緩存

ibatis的動態標籤分爲一元條件元素標籤和二元條件元素標籤:app

 

一元條件元素框架

<isPropertyAvailable>學習

檢查是否存在該屬性(存在parameter bean的屬性)。對象

<isNotPropertyAvailable>開發

檢查是否不存在該屬性(不存在parameter bean的屬性)。rem

<isNull>

檢查屬性是否爲null。

<isNotNull>

檢查屬性是否不爲null。

<isEmpty>

 

檢查Collection.size()的值,屬性的String或String.valueOf()值,是否爲null或空(「」或size() < 1)。

 

<isNotEmpty>

 

檢查Collection.size()的值,屬性的String或String.valueOf()值,是否不爲null或不爲空(「」或size() > 0)。 例子:

 <isNotEmpty prepend=」AND」 property=」firstName」 > FIRST_NAME=#firstName# </isNotEmpty>

 

 

二元條件元素

<isEqual>

比較屬性值和靜態值或另外一個屬性值是否相等。

<isNotEqual>

比較屬性值和靜態值或另外一個屬性值是否不相等。

<isGreaterThan>

比較屬性值是否大於靜態值或另外一個屬性值。

<isGreaterEqual>

比較屬性值是否大於等於靜態值或另外一個屬性值。

<isLessThan>

比較屬性值是否小於靜態值或另外一個屬性值。

<isLessEqual>

比較屬性值是否小於等於靜態值或另外一個屬性值。 例子: <isLessEqual prepend=」AND」 property=」age」 compareValue=」18」> ADOLESCENT = ‘TRUE’ </isLessEqual>

 

         prepend - 可被覆蓋的SQL語句組成部分,添加在語句的前面(可選)

         property - 被比較的屬性(必選)
         compareProperty - 另外一個用於和前者比較的屬性(必選或選擇compareValue)
         compareValue - 用於比較的值(必選或選擇compareProperty)

         還有兩個其它的條件元素,<isParameterPresent>,<iterate>就不說了,用到的時候能夠再查。

 

ibatis 動態標籤的嵌套

        說到動態標籤,那就不得不說一下動態標籤的嵌套查詢了。在我進行項目開發的時候,因爲存在一個查詢報表的功能,該功能涉及到的數據庫表特別多,因此查詢條件很是複雜,這時候不得不要到動態標籤的嵌套查詢了。例如:

<dynamic>
<isEqual property="reimburseType" compareValue="1">
left join
(
select ReimbursementRevisionId
from f_reimbursement_type_travel
where 1=1
<isNotNull prepend="and" property="BusinessPersonName">
BusinessPersonName = #applicationType#
</isNotNull>
<isNotNull prepend="and" property="Position">
Position = #Position#
</isNotNull>
)as rtt
on rr.ReimbursementRevisionId = rtt.ReimbursementRevisionId
</isEqual>
</dynamic>

       理論上來講,動態標籤是能夠任意嵌套的,好比<isEqual>裏面能夠嵌套<isEqual>;可是嵌套也有一些要求,好比,<dynamic>標籤裏面就不能嵌套<dynamic>標籤,另外我還發現<isGreaterEqual>裏嵌套<isLessEqual>不能實現預期的功能,好比我想在detailType屬性在3-6,8-10時,執行查詢語句,代碼以下:

<isGreaterEqual property="detailType" compareValue="3">
<isLessEqual property="detailType" compareValue="10">
<isNotEqual property="detailType" compareValue="7">
join
(
select ProjectRevisionId,sum(DetailAmount) as DetailTotalAmount
from f_reimbursement_detail
group by ProjectRevisionId
where DetailTypeId = #detailType#
having 1=1
<isNotEmpty prepend="and" property="detailAmountMin">
DetailTotalAmount <![CDATA[>=]]> #detailAmountMin#
</isNotEmpty>
<isNotEmpty prepend="and" property="detailAmountMax">
DetailTotalAmount <![CDATA[<=]]> #detailAmountMax#
</isNotEmpty>
) as rf on rf.ProjectRevisionId = rr.ProjectRevisionId
</isNotEqual>
</isLessEqual>
</isGreaterEqual>
若是傳參detailType=5,運行事後,發現程序在執行上面代碼時sql語句中並無以上的語句,可是若是隻是下面這樣寫,則一點問題也沒有,這讓我很鬱悶。

<isGreaterEqual property="detailType" compareValue="3">
join
(
select ProjectRevisionId,sum(DetailAmount) as DetailTotalAmount
from f_reimbursement_detail
group by ProjectRevisionId
where DetailTypeId = #detailType#
having 1=1
<isNotEmpty prepend="and" property="detailAmountMin">
DetailTotalAmount <![CDATA[>=]]> #detailAmountMin#
</isNotEmpty>
<isNotEmpty prepend="and" property="detailAmountMax">
DetailTotalAmount <![CDATA[<=]]> #detailAmountMax#
</isNotEmpty>
) as rf on rf.ProjectRevisionId = rr.ProjectRevisionId
</isGreaterEqual-->
 

ibatis使用過程當中應該知道的知識:

 

1.佔位符

          #是佔位符,$是字符串拼接。id = #id# 生成的sql語句是 id = ? 使用的是PreparedStatement,執行時,經過setXXX方法,將值加入到sql語句中。

若字段id爲String類型,傳遞的參數id爲1, 
則 id = #id# 實際SQL爲:select * from user where a = ‘1’; 
而 id = $id$ 實際SQL爲:select * from user where a = 1; 
注:儘可能用#id# 而不要用$id$ ,由於後面這種只是拼接,很容易被sql注入攻擊。
 

2.動態生成查詢的結果列:

         有時會出現不能動態生成查詢結果列的狀況,那是由於ibaits 會緩存查詢的meta信息,因此在生成動態列時必定要加上 remapResults="true"。

 

<select id="getxx" resultClass="java.util.HashMap" parameterClass="map" remapResults="true">
 

3.動態指定表名

           有時會碰到2張表結構相同,可是表名不同的狀況,這時候查詢語句中的表名就須要動態指定了。這時只能用$tableName$,而不能用#tableName#。

 

select * from $tableName$ where id = #id#
 

4.動態標籤裏面的屬性

1)dynamic的prepend只要檢測到第一個條件爲「真」的比較元素,則覆蓋其prepend屬性並組裝where關鍵字爲動態SQL的一部分。 若果dynamic下面第一條動態標籤不含prepend屬性,則會覆蓋第二個條件爲「真」的動態標籤的prepend屬性值,全部最好每一個動態標籤都加上prepend屬性。
2)isNotNull的prepend='and' 只要檢測到參數值知足比較條件,則前置組裝and關鍵字爲動態SQL的一部分。

 

5.動態sql片斷

//動態sql片斷 <sql id="sql_count"> select count(*) </sql> <sql id="sql_select"> select * </sql> <sql id="sql_where"> from student <dynamic prepend="where"> <isNotEmpty prepend="and" property="name"> name like '%$name$%' </isNotEmpty> <isNotEmpty prepend="and" property="no"> no like '%no$%' </isNotEmpty> </dynamic> </sql> <select id="findStudentCount" parameterClass="map" resultClass="int"> <include refid="sql_count"/> <include refid="sql_where"/> </select> <select id="findStudent" parameterClass="map" resultMap="student.result_base"> <include refid="sql_select"/> <include refid="sql_where"/>

相關文章
相關標籤/搜索