• iBatis.Net系列(五) ParameterMap


    在用 Ado.Net 进行数据库访问操作中,最麻烦的就是准备 DbCommand 必须为它添加 DbParameter ,特别是当要传的参数特别多的情况下,数据访问层的很多代码都是花在这里。 iBatis ParameterMap 配置就是针对这个问题所提出的一种解决方案,基于 xml 的配置,把字段名和对象的属性对应起来,通过运行时的一些工作,自动为 DbCommand 提供它所需的参数集合。从而避免了我们直接写很多重复代码。

    Employees_ParameterMap.xml 配置文件中:

    < select id = "Employees_SelectWithParameterClass " parameterClass = "Employee " resultClass = "Employee " listClass = "ArrayList ">

        SELECT EmployeeID,LastName,FirstName FROM Employees WHERE EmployeeID = #EmployeeID# OR LastName = #LastName#

    </ select >

    使用的是内联参数映射的方式,语句的在执行查询时只需为它提供 Employee 类型的对象,它就会自动去读自己需要的 EmployeeID LastName 属性的值,返回查询结果。在执行时它所执行的语句如下:

    [SELECT EmployeeID,LastName,FirstName FROM Employees WHERE EmployeeID =  @param0  OR LastName =  @param1]

    所需的参数的提供方式如下:

    [@param0=[EmployeeID,12], @param1=[LastName,8bbb7bfb-c]]

    并且,在 iBatis 中还会指出各个参数的类型:

    [@param0=[Int32, System.Int32], @param1=[String, System.String]]

    对于下面这个配置:

    < select id = "Employees_SelectWithParameterMap1 " parameterMap = "Employee_SelectParameterMap " resultClass = "Employee " listClass = "ArrayList ">

            SELECT EmployeeID,LastName,FirstName FROM Employees WHERE EmployeeID = #EmployeeID# OR LastName = #LastName# OR Country = #Country#

        </ select >

    它所使用的ParameterMap 配置如下:

        < parameterMap class = "Employee " id = "Employee_SelectParameterMap ">

            < parameter column = "EmployeeID " property = "EmployeeID " dbType = "int " type = "int " direction = "Input "/>

            < parameter column = "LastName " property = "LastName " dbType = "nvarchar " type = "string " direction = "Input "/>

            < parameter column = "Country " property = "Country " dbType = "nvarchar " type = "string " direction = "Input "/>

        </ parameterMap >

    在每一个 Parameter 映射元素可以指定每个属性对应的列,它的类型和对应的数据库的类型,还可以指定当它为空值时的默认值,具体可以参看官方文档。但是可以看到,我们期待它能和内联参数一样的使用方法,如上配置的那样。可是行不行呢?从程序的执行结果来看,是不可以的。由于之前在配置 SQL 语句的时候基本都是使用内联参数没有特别注意到这点。在使用 Parameter Map 的时候是不能用 #property# 的形式显示地指定要使用的属性参数,只能通过“ ? ”,顺序替代每一个 parameter 元素,如下:

    < select id = "Employees_SelectWithParameterMap2 " parameterMap = "Employee_SelectParameterMap " resultClass = "Employee " listClass = "ArrayList ">

                SELECT EmployeeID,LastName,FirstName FROM Employees WHERE EmployeeID = ? OR LastName = ? OR Country = ?

        </ select >

    可以看到,由于没有明显地指出EmployeeID 对应哪个属性,那如果把上面的parameter 元素调换一下,那么EmployeeID 所对应的参数值就发生变化了。同时,也是这个原因,通过这种方式的参数映射,就无法重复利用每个参数了。如果仔细观察会发现,既然都指定了column 属性了,那它为什么不会自动去配置呢?其实在这边column 属性是不起作用的,它只会作用在执行存储过程的时候。也就是说上面的Parameter 元素中的column 属性不是必须的。下面是一个存储过程的例子:

    < procedure id = "Employee_InsertWithProcedure " parameterMap = "Employee_InsertParameterMap2 " resultClass = "int ">

        InsertEmployee

    </ procedure >

        InsertEmployee 接受两个参数@LastName@FirstName 。我给它提供的映射参数如下:

    < parameterMap class = "Employee " id = "Employee_InsertParameterMap2 ">          

        < parameter column = "LastName " property = "LastName " dbType = "nvarchar " type = "string " direction = "Input "/>

        < parameter column = "FirstName " property = "FirstName " dbType = "nvarchar " type = "string " direction = "Input "/>

    </ parameterMap >

        上面这样的配置的结果是(其中逗号后面的是值):

    [@LastName=[LastName,9a8bc059-3], @FirstName=[FirstName,46887db0-2]]

    但是当我把他们的位置调换了一下。它的结果如下:

    [@LastName=[ FirstName,9a8bc059-3], @FirstName=[LastName,46887db0-2]]

    也就是对储存过程也是一样的,参数映射关系仍然与 parameter 元素的顺序息息相关的。 Column 属性仍然没有显示出它的作用。所以使用ParameterMap 还有是有一定的局限性的。但是对存储过程来说,就必须使用这样的方式,因为它只支持ParameterMap 为它提供参数,而不支持内联参数。

    最后总结列出几点ParameterMap 需要特别注意的几个细节:

    1 .在配置ParameterMap 的时候,如果传入的参数对像是元数据类型(int,string etc ),那么在配置Parameter 元素的时候,property 的属性名使用value 。通过这种情况主要使用在为存储指定参数的情况下。

    2 .如果 ParameterMap 中配置的parameter 元素不包含在传入参数对象中(属性或IDictionary 对象的一个key,value 项),将会产生异常,而不管在statement 中有没有用到。

    3 .在使用parameterMapextends 属性时,它将会继承extends 值对应的parameterMap 配置,并且会继承它的所有的参数映射,并且顺序是从继承的那配置为基准开始计算。这个在需要用到extends 属性的时候要特别注意。

    4. 在为存储过程传参过程要特别注意,参数映射与存储过程的参数之间的顺序对应要正确。而且必须为提供与存储过程足够的参数(parameter 配置足够多) ,即使存储过程的部分参数已经有默认值了。否则将抛出System.ArgumentOutOfRangeException 异常。

    5 .正常情况下,应该尽量使用内联参数。

    源代码下载

    阿不 http://hjf1223.cnblogs.com
  • 相关阅读:
    [BZOJ4825][HNOI2017]单旋(线段树+Splay)
    [BZOJ4542][HNOI2016]大数(莫队)
    [LOJ6281]数列分块入门 5
    [LOJ6280]数列分块入门 4
    [LOJ6279]数列分块入门 3
    [LOJ6278]数列分块入门 2
    [LOJ6277]数列分块入门 1
    [BZOJ2120]数颜色
    [BZOJ3585]mex
    [ZJb417]区间众数
  • 原文地址:https://www.cnblogs.com/cpcpc/p/2123139.html
Copyright © 2020-2023  润新知