iBATIS笔记之数据映射工作方式

  数据映射定义在一个描述文件中。通过使用iBATIS提供的常规服务,XML描述文件会呈现在客户端对象中。为了访问你的数据地图,应用程序会向客户端对象发出请求并传递所需的statement名称。

XML描述文件内容(也称Data Map definition file)

EX3.1  A Simple Data Map

<?xml version="1.0" encoding="UTF-8" ?>
  <sqlMap namespace="LineItem"
xmlns="http://ibatis.apache.org/mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" >
<!--Type aliases allow you to use a shorter name for long fully qualified class names.-->
    <alias>
        <typeAlias alias="LineItem" type="NPetshop.Domain.Billing.LineItem, NPetshop.Domain" />
    </alias>
    <statements>
        <insert id="InsertLineItem" parameterClass="LineItem">
            INSERT INTO [LinesItem]
            (Order_Id, LineItem_LineNum, Item_Id, LineItem_Quantity, LineItem_UnitPrice)
            VALUES
            (#Order.Id#, #LineNumber#, #Item.Id#, #Quantity#, #Item.ListPrice#)
        </insert>
    </statements>
  </sqlMap>

此映射从LineItem实例中获取参数传入statements中,因此添加值得sql语句从项目代码中分离出来。而且我们可以直接对应一个库方法:

Mapper.Instance().Insert(“InsertLineItem”,lineItem);

 

EX3.2  A Data Map definition file with some bells and whistles

<?xml version="1.0" encoding="UTF-8" ?>
 <sqlMap namespace="Product"     //此命名空间和下文中的class有何关联或区别?
xmlns="http://ibatis.apache.org/mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" >
//给type对应的类定义别名
<alias>
        <typeAlias alias="Product" type="Example.Domain.Product, Example.Domain" />
     </alias>
    //设定缓存参数
    <cacheModels>
        <cacheModel id="productCache" implementation="LRU">   //???
            <flushInterval hours="24"/>   //维持时间上限为24小时
            <property name="CacheSize" value="1000" />   //保存记录数上限为1000条
        </cacheModel>
    </cacheModels>
    //设定结果映射
    <resultMaps>
        //将两个结果列和对象的两个属性建立映射
        <resultMap id="productResult" class="Product">
            <result property="Id" column="Product_Id"/>
            <result property="Description" column="Product_Description"/>
        </resultMap>
    </resultMaps>
    //设定SQL statement
    <statements>
        //”?”对应着参数位置,parameterMap表示参数来源,cacheModel表示缓存参数设定
        <select id="GetProduct" parameterMap="productParam" cacheModel="productCache">
            select * from Products where Product_Id = ?
        </select>
    </statements>
    //设定传入参数
    <parameterMaps>
        //将statement中的?与对象的Id属性建立映射
        <parameterMap id="productParam" class="Product">
            <parameter property="Id"/>
        </parameterMap>
    <parameterMaps>
  </sqlMap>

  许多敏捷型开发人员会先写成EX3.1的形式,之后再添加诸如缓存等等的特性。当你将映射从EX3.1改变成EX3.2的形式之后,虽然变的更长更复杂,但与程序代码之间的耦合降至了最低。

  在一个Data Map定义中可以依你所想添加多个cache models、别名、resultMaps、parameterMaps和statements元素,所有定义会被加载到同一个configuration中,因此你可以在一个DataMap中使用定义在另一个DataMap中的元素。

EX3.3 Statement element syntax(句法)

<statement id="statement.name"
    [parameterMap="parameterMap.name"]
    [parameterClass="alias"]
    [resultMap="resultMap.name"]
    [resultClass="class.name|alias"]
    [listClass="class.name|alias"]
    [cacheModel="cache.name"]
    [extends="statement.name"]
>
    select * from Products where Product_Id = [?|#propertyName#]
    order by [$simpleDynamic$]
</statement>

中括号内的项是可选的,甚至有些项之间是互相排斥的。

1. statement类型

statement元素可以说是一种万能元素,任何sql statement都可以在此元素标记范围内定义。这很好,但更多特定的元素类型提供了更好的检错及其他的一些功能。如第一章示例中的insert元素。下表中总结了statement不同类型的元素和他们支持的属性、特殊字段。

 

The six statement-type elements

Statement Element

Attributes

Child Elements

Methods

<statement>

id

parameterClass

resultClass

listClass

parameterMap

resultMap

cacheModel

All dynamic elements

Insert

Update

Delete

All query methods

<insert>

id

parameterClass

parameterMap

All dynamic elements

            <selectKey>

            <generate>

Insert

Update

Delete

<update>

id

parameterClass

parameterMap

extends

All dynamic elements

            <generate>

Insert

Update

Delete

<delete>

id

parameterClass

parameterMap

extends

All dynamic elements

            <generate>

Insert

Update

Delete

<select>

id

parameterClass

resultClass

listClass

parameterMap

resultMap

cacheModel

extends

All dynamic elements

            <generate>

Insert

Update

Delete

<procedure>

id

parameterMap

resultClass

resultMap

cacheModel

All dynamic elements

Insert

Update

Delete

All query methods

2.存储过程

    iBATIS将存储过程视作另一种statement类型,使用方法如下所示:

EX3.4 A Data Map using a stored procedure

<!-- Microsot SQL Server -->
<procedure id="SwapEmailAddresses" parameterMap="swap-params">
    ps_swap_email_address
</procedure>
...
<parameterMap id="swap-params">
    <parameter property="email1" column="First_Email" />
    <parameter property="email2" column="Second_Email" />
</parameterMap>

此例的功能是交换数据库的两列中存储的两个Email地址,当然同时也对参数对象进行同样操作。

NOTE:对于.NET而言,parameterMap是必需的,DBType, parameter direction, size, precision, scale等属性通常由框架依据你的Provider自动去发现。(基于CommandBuilder)如果你的存储过程没有参数,则此属性为可选的。

 

3.SQL片段的重用

<sql id="selectItem_fragment">
    FROM items
    WHERE parentid = #value#
</sql>
<select id="selectItemCount" parameterClass="int" resultClass="int">
    SELECT COUNT(*) AS total
    <include refid="selectItem_fragment"/>
</select>
<select id="selectItems" parameterClass="int" resultClass="Item">
    SELECT id, name
    <include refid="selectItem_fragment"/>
</select>

<sql>标记内的是要重用的片段,<include>标记指示要重用哪个片段。在很多情况下,也可以使用statement标记中的extends属性达到同样的目标。

4.调解XML标记冲突

       由于在文档中同时使用了SQL语言和XML语言,因此会出现冲突。最常见的冲突就是>和<标记的冲突。SQL语言将此用作运算符,而XML以之为标记。一个简单的解决方法是,构建CDATA元素。

<statement id=”SelectPersonsByAge” parameterClass=”int” resultClass=”Person”>
    <![CDATA[
    SELECT * FROM PERSON WHERE AGE>#value#
    ]]>
</statement>

5.自动生成键

       许多数据库系统支持自动生成主键域,作为一种扩展功能。有些供应商采用预生成模式,有些采用后生成模式。不管哪一种,你都可以通过iBATIS技术中的<insert>元素中插入<selectKey>节的方式,获取一个预生成的主键。

<!—Microsoft SQL Server IDENTITY Column Example-->
<insert id=”insert    Product-MS-SQL” parameterClass=”product”>
    insert into PRODUCT (PRD_DESCRIPTION)
    values (#description#)
<selectKey resultClass=”int” type=”post” property=”id”>
    select @@IDENTITY as value
</selectKey>
</insert>

6.<generate>标记

使用<generate>标记,可以基于<parameterMap>元素中的参数,自动创建简单的SQL statement节。支持增删改查四种基本语句。

<parameterMaps>
    <parameterMap id="insert-generate-params">
        <parameter property="Name" column="Category_Name"/>
        <parameter property="Guid" column="Category_Guid" dbType="UniqueIdentifier"/>
     </parameterMap>
    <parameterMap id="update-generate-params" extends="insert-generate-params">
          <parameter property="Id" column="Category_Id" />
    </parameterMap>
    <parameterMap id="delete-generate-params">
         <parameter property="Id" column="Category_Id" />
         <parameter property="Name" column="Category_Name"/>
    </parameterMap>
    <parameterMap id="select-generate-params">
         <parameter property="Id" column="Category_Id" />
         <parameter property="Name" column="Category_Name"/>
         <parameter property="Guid" column="Category_Guid" dbType="UniqueIdentifier"/>
    </parameterMap>
</parameterMaps>

<statements>
    <update id="UpdateCategoryGenerate" parameterMap="update-generate-params">
        <generate table="Categories" by="Category_Id"/>
    </update>
    <delete id="DeleteCategoryGenerate" parameterMap="delete-generate-params">
        <generate table="Categories" by="Category_Id, Category_Name"/>
    </delete>
    <select id="SelectByPKCategoryGenerate" resultClass="Category" parameterClass="Category" parameterMap="select-generate-params">
        <generate table="Categories" by="Category_Id"/>
    </select>
    <select id="SelectAllCategoryGenerate" resultClass="Category" parameterMap="select-generate-params">
        <generate table="Categories" />
    </select>
    <insert id="InsertCategoryGenerate" parameterMap="insert-generate-params">
        <selectKey property="Id" type="post" resultClass="int">
            select @@IDENTITY as value
        </selectKey>
        <generate table="Categories" />
    </insert>
</statements>

NOTE:对应的SQL语句是在DataMapper实例化是就创建的,所以执行时不会有性能上的影响。使用<generate>标记不支持blobs等供应商的特殊类型,也不能简化复杂的SQL语句做到化繁为简,但它却做到了简者更简。

posted @ 2016-03-14 13:35  大木水可  阅读(237)  评论(0编辑  收藏  举报