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

来源:互联网 发布:快消品集团网络商学院 编辑:程序博客网 时间:2024/06/03 10:12

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文档。

原创粉丝点击