4.IBatis框架的SQL Map映射文件

IBatis框架中,利用一個映射文件來定義需要持久化的對象,在這個文件中SQL語句是最顯眼的,這個映射文件的目的就是將SQL映射到對象。下面先看一下映射文件的主要功能:

q        定義一個持久化的Java類。

q        映射VO中的變量屬性爲表字段。

q        根據SQL來持久化對象。

q        可以定義隨意使用的SQL

q        支持各種條件語句的定義。

q        支持數據庫自動主鍵的生成。

q        支持存儲過程。

q        支持將結果映射成XML文檔。

q        支持多表關聯。

1. 一個具體映射文件的示例

下面看一個具體映射文件的示例。在這之前,表結構和VO將沿用第十一章的例11.2 AttackSolution.java,從這裏可以看出,IBatis框架的VO也是一個POJO。映射文件的文件名可以隨意指定,只要在sql_map_config.xml中的<sqlMap>元素定義中與之對應即可。

與例12.1 sql_map_config.xml<sqlMap>元素對應的,將定義映射文件名爲fw_attacksolution_SqlMap.xml,示例見12.2,在示例12.2中將分段解釋各個應用:

12.2fw_attacksolution_SqlMap.xml

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE sqlMap PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN" "http://ibatis.apache.org/dtd/sql-map-2.dtd">

 

<sqlMap namespace="fw_attacksolution">

映射文件的根節點是<sqlMap>namespace是該<sqlMap>的命名空間,因爲SQL Map映射文件可以有多個,而對於SQL Map來說所有映射文件都是全局性的。這意味着在SQL Map中的標識只能是惟一的,利用namespace和標識的全限定名就可以進行區別,前提是,配置文件中的useStatementNamespaces屬性必須設置爲true

  <resultMap id="fwAttacksolutionResult"

 class="struts.sample.cap11.sample2.entity.Attacksolution">

    <result column="attack_event_code" property="attack_event_code" jdbcType="VARCHAR" />

    <result column="attack_mean" property="attack_mean" jdbcType="VARCHAR" />

    <result column="attack_action" property="attack_action" jdbcType="VARCHAR" />

  </resultMap>

<resultMap>元素是最常用的元素,使用<resultMap>元素可以定義數據返回的對象。其id屬性在之後的各種帶返回對象的元素中,將作爲返回對象的標識。即,返回結果將會以calss屬性定義的對象作爲承體。本例中定義返回結果到VO對象Attacksolution

<resultMap>元素的子元素以column屬性作爲數據庫表字段、並以property字段作爲VO變量屬性進行映射。返回結果根據字段設置VO變量屬性的值。jdbcType屬性則指定了數據庫表中字段的數據庫類型。

  <!--定義一般的SQL語句,通常用來作爲動態SQL語句的指定。id屬性被用作對整個動態SQL語句的標識。 -->

<sql id="example_Where_Clause">

  <!-- <dynamic>元素可以劃分出SQL語句的動態部分。動態部分可以包含任意多的條件元素。條件元素決定,是否在語句中包含其中的SQL代碼。-->

  <!-- prepend屬性是動態SQL代碼的一部分,prepend屬性值會被用來覆蓋第一個條件元素。 -->

<dynamic prepend="where">

  <!-- isPropertyAvailable用來作爲一個條件判斷元素,它判斷是否存在property屬性所指定的某個對象的變量屬 -->

  <!-- prepend屬性指定了條件元素-->

      <isPropertyAvailable prepend="and" property="AND_attack_event_code_NULL">

<!-- 若存在該變量屬性,則指定可以使用<isPropertyAvailable>元素的實體內容。-->

        attack_event_code is null

      </isPropertyAvailable>

      <isPropertyAvailable prepend="and" property="AND_attack_event_code_NOT_NULL">

        attack_event_code is not null

      </isPropertyAvailable>

      <isPropertyAvailable prepend="or" property="OR_attack_event_code_NOT_NULL">

        attack_event_code is not null

      </isPropertyAvailable>

      <isPropertyAvailable prepend="and" property="AND_attack_event_code_EQUALS">

        <!-- 用“#”包含起來的內容是某個對象中的變量屬性 -->

        attack_event_code = #attack_event_code#

      </isPropertyAvailable>

      <isPropertyAvailable prepend="or" property="OR_attack_event_code_EQUALS">

        <!-- 用“#”包含起來的內容是某個對象中的變量屬性 -->

        attack_event_code = #attack_event_code#

      </isPropertyAvailable>

    </dynamic>

  </sql>

以本例中最後一個<isPropertyAvailable>來說明:當某個對象存在變量屬性OR_attack_event_code_EQUALS時,將定義“or attack_event_code = ?”的條件語句,並判斷是否是第一個條件。如果是第一個條件則會以“where”來替換“or”,成爲“where attack_event_code = ?”,而“?”將以某個對象中變量屬性attack_event_code的值來替換。

說明:在本例中,OR_attack_event_code_EQUALS並不是VO對象的變量屬性,因此將會有一個新的Java類來提供該變量屬性,這在之後的介紹中可以看到,這種做法是非常靈活的。

  <!-- 定義所有的查詢SQL -->

  <!-- id聲明瞭該查詢的惟一標識 -->

<!-- resultMap屬性與<resultMap>元素的id屬性匹配表示結果映射到的VO,當查詢結果是多條記錄時,會返回一個集合 -->

<!-- parameterClass屬性是傳入參數的類,該類在這裏必須使用全限定名-->

<select id="selectByPrimaryKey"

resultMap="fwAttacksolutionResult"

parameterClass="struts.sample.cap11.sample2.entity.Attacksolution">

    <!-- <select>元素的實體內容爲SQL語句,其中由“#”包含的內容將根據parameterClass屬性指定的對象中找到匹配的變量屬性值。 -->

    select attack_event_code,

          attack_mean,

          attack_action

    from fw_attacksolution

    where attack_event_code = #attack_event_code#

  </select>

本例中,該<select>元素的含義是:以帶條件的預處理SQL查詢表fw_attacksolution,條件的“?”參數將通過struts.sample.cap11.sample2.entity.Attacksolution類的attack_event_code變量屬性得到,查詢結果被返回到<resultMap>元素所指定的VO struts.sample.cap11.sample2.entity.Attacksolution中。

  <select id="selectByExample"

resultMap="fwAttacksolutionResult"

parameterClass="java.util.Map">

    select attack_event_code,

          attack_mean,

          attack_action

from fw_attacksolution

<!-- <include>子元素可以包含動態SQL<select>元素的實體內容中去-->

<!-- 屬性refid指定被包含的動態SQL標識,該標識是全局性的-->

<include refid=" fw_attacksolution.example_Where_Clause"/>

<!-- 判斷property屬性所指定的對象變量屬性是否存在 -->

<isPropertyAvailable property="ORDER_BY_CLAUSE">

  <!-- 使用“$”,包含的是變量屬性值 -->

      order by $ORDER_BY_CLAUSE$

    </isPropertyAvailable>

  </select>

以上這部分仍然使用<select>元素來定義一句查詢SQL,不過這部分的SQL複雜一些,因爲這是一句動態SQL。在本例中需要注意的是,SQL的傳入參數被使用parameterClass屬性指定的java.util.Map來傳入,這個Map的內容必須符合Map實例put(method, value),在底層框架處理時會如同得到一個POJO的變量屬性名、變量屬性值一樣來取得這個Map中的每一行作爲參數名和參數值。

本例的含義是:當傳入參數中存在“ORDER_BY_CLAUSE”變量屬性時,就將“ORDER_BY_CLAUSE”的值替換$ORDER_BY_CLAUSE$,形成一句完整的order by語句。

說明:“$”和“#”同樣都是替換變量屬性的值,有什麼區別呢?“$”是一般的替換,用變量屬性值來替換“$”包含的內容。而“#”與“$”完全是處理方式的區別,包含在“#”中的變量屬性值會被用來在帶“?”的SQL中替換“?”,進行SQL預處理。

  <delete id="deleteByPrimaryKey"

parameterClass="struts.sample.cap11.sample2.entity.Attacksolution">

    delete from fw_attacksolution

    where attack_event_code = #attack_event_code#

  </delete>

<delete>元素也是執行一句SQL,但是它執行的是刪除功能的SQL<delete>元素擁有idparameterClassparameterMap三種屬性,但是沒有resultClassresultMap這兩個返回性質的屬性,所以<delete>元素執行後的SQL是無返回值的。

  <delete id="deleteByExample"

parameterClass="java.util.Map">

    delete from fw_attacksolution

    <include refid="fw_attacksolution.example_Where_Clause"/>

  </delete>

以上也是一個<delete>元素執行的刪除語句,惟一不同的是它有了動態SQL的特性,所以<delete>元素支持所有的動態SQL

  <insert id="insert"

parameterClass="struts.sample.cap11.sample2.entity.Attacksolution">

    <!-- 要顯式地聲明數據庫中對應字段的類型 -->

    insert into fw_attacksolution (attack_event_code, attack_mean,

      attack_action)

    values (#attack_event_code:VARCHAR#, #attack_mean:VARCHAR#,

      #attack_action:VARCHAR#)

  </insert>

<insert>元素執行的是新增記錄的SQL語句,它的特性和<delete>元素類似。本例中的insert語句會爲表fw_attacksolution插入一條記錄,記錄中的每個字段都是VARCHAR型,通過parameterClass屬性指定的對象來傳入變量屬性值。

  <update id=" updateByPrimaryKey"

parameterClass="struts.sample.cap11.sample2.entity.Attacksolution">

    update fw_attacksolution

    set attack_mean = #attack_mean:VARCHAR#,

      attack_action = #attack_action:VARCHAR#

    where attack_event_code = #attack_event_code#

  </update>

</sqlMap>

<update>元素執行的是更新記錄的SQL語句,它的特性和<delete><insert>元素一樣,也必須顯式地聲明所更新的數據庫表字段的類型,支持所有的動態SQL

2. 其他條件判斷元素和屬性

IBatis框架對於動態SQL的支持不僅提供了<isPropertyAvailable>元素,還提供了其他類似的元素,如下所示:

q        <isNotPropertyAvailable>元素:當不存在對象的變量屬性時,可以使用元素的實體內容。

q        <isNull>元素:當對象的變量屬性爲null時可以使用元素的實體內容。

q        <isNotNull>元素:當對象的變量屬性不爲null時可以使用元素的實體內容。

q        <isEmpty>元素:檢查對象的變量屬性爲空時可以使用元素的實體內容。

q        <isNotEmpty>元素:檢查對象的變量屬性不爲空時可以使用元素的實體內容。

以上這些元素都擁有prepend屬性和property屬性,property屬性被作爲某個對象的變量屬性。prepend屬性指定了條件元素,具體如下所示:

q        <isEqual>元素:在比較對象與對象之間的變量屬性,或對象與靜態值相等的條件下,可以使用元素的實體內容。

q        <isNotEqual>元素:在比較對象與對象之間的變量屬性,或對象與靜態值不相等的條件下,可以使用元素的實體內容。

q        <isGreaterThan>元素:比較對象與對象之間的變量屬性,或對象與靜態值是否存在前者大於後者的情況,若存在,可以使用元素的實體內容。

q        <isGreaterEqual>元素:比較對象與對象之間的變量屬性,或對象與靜態值是否存在前者大於且等於後者的情況,若存在,可以使用元素的實體內容。

q        <isLessThan>元素:比較對象與對象之間的變量屬性,或對象與靜態值是否存在前者小於後者的情況,若存在,可以使用元素的實體內容。

q        <isLessEqual>元素:比較對象與對象之間的變量屬性,或對象與靜態值是否存在前者小於且等於後者的情況,若存在,可以使用元素的實體內容

以上這些元素都擁有:prependpropertycomparePropertycompareValue四個屬性。prepend屬性指定了條件元素;property指定了某個對象的變量屬性;compareProperty作爲另一個對象的變量屬性與property指定的某個對象的變量屬性進行比較;compareValue作爲一個靜態值與property指定的某個對象的變量屬性進行比較。comparePropertycompareValue屬性至少使用一個。

3. <select>元素的其他屬性

<select>元素中,除了本例所提供的屬性外,還提供了resultClassparameterMap兩個可選屬性。

q        resultClass屬性明確指定了返回結果的全限定名對象。resultClass並不常用,因爲它沒有了映射數據庫字段的持久化特性。

q        parameterMap屬性則指定了傳入參數的一個標識,讀者可以想象到,同樣會由<parameterMap>元素來定義一個傳入參數的對象,並用id來惟一標識它。的確如此,<parameterMap><resultMap>的寫法十分類似,但它不必要映射到表中字段,因爲僅僅是作爲一個傳入參數的對象沒有持久化的概念。<parameterMap>元素並不常用,parameterMap屬性也不常用,一般來說用parameterClass屬性已經足夠滿足大多數的需要了。

4.其他SQL執行元素

除了本例中所見到的執行SQL的元素外,IBatis框架還提供了其他的SQL執行元素。

q        <statement>元素,通用的SQL執行元素,可以執行任何SQL語句。在上例中的所有SQL語句,都可以使用<statement>元素來替換。<statement>元素還提供了一個新的屬性xmlResultName作爲將返回結果生成一個XML文檔。

q        <procedure>元素,用於執行存儲過程。<procedure>元素也提供了xmlResultName屬性來返回結果生成XML文檔。

發佈了19 篇原創文章 · 獲贊 6 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章