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.2:fw_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>元素拥有id、parameterClass和parameterMap三种属性,但是没有resultClass和resultMap这两个返回性质的属性,所以<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>元素:比较对象与对象之间的变量属性,或对象与静态值是否存在前者小于且等于后者的情况,若存在,可以使用元素的实体内容
以上这些元素都拥有:prepend、property、compareProperty、compareValue四个属性。prepend属性指定了条件元素;property指定了某个对象的变量属性;compareProperty作为另一个对象的变量属性与property指定的某个对象的变量属性进行比较;compareValue作为一个静态值与property指定的某个对象的变量属性进行比较。compareProperty和compareValue属性至少使用一个。
3. <select>元素的其他属性
<select>元素中,除了本例所提供的属性外,还提供了resultClass、parameterMap两个可选属性。
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文档。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值