zoukankan      html  css  js  c++  java
  • iBATIS.net调用存储过程

    前言:这篇整理好已经很久了,一直觉得还有很多需要改进的地方,然后拖着等待完善,nnd,竟然等成跨年贴了。现在把它发布一下,将来自己可能会用到,同时希望对您有帮助。

    一、存储过程分类
    这里我们把存储过程大致分为两类:查询类型的存储过程和更新类型的存储过程。
    1、查询类型的存储过程
    可以直接理解为Select查询类型的存储过程,其实任何不曾改变数据库数据的存储过程都可以归为这一类。
    2、更新类型的存储过程
    这一类型的您可以直接理解为Insert,Update和Delete类型的存储过程,其实任何改变数据库数据的存储过程都可以归为这一类。
    ps:上面这两点纯粹是个人片面理解,难免有不严谨的地方,高手54.

    二、iBATIS.net调用存储过程
    我们继续前面几篇介绍的iBATIS.Net的例子,简单改进为调用存储过程的方法。
    1、查询类型
    创建一个存储过程,这个存储过程按照名字模糊查找特定的记录:

    代码
    USE [Northwind]
    GO

    CREATE  PROCEDURE [dbo].[ProcGetPersonByName] 
        
    @FirstName varchar(50),
        
    @LastName varchar(50)
    AS
    BEGIN
        
        
    SELECT
        PER_ID Id,
        PER_FIRST_NAME FirstName,
        PER_Last_NAME LastName,
        PER_BIRTH_DATE BirthDate,
        PER_WEIGHT_KG Weight,
        PER_HEIGHT_M Height
        
    FROM
        Person (NOLOCK)
        
    WHERE
        PER_FIRST_NAME 
    LIKE '%'+@FirstName+'%'
        
    OR 
        PER_Last_NAME 
    LIKE '%'+@LastName+'%'    
    END

     然后,我们在xml的statements节点中配置如下:

     <!--调用查询类型的存储过程-->
        
    <procedure id="SelectByName" parameterMap="ParamSelect"  resultMap="ResultPerson">
          ProcGetPersonByName
        
    </procedure>

     需要说明的是,在procedure节点中,parameterMap和resultMap也需要我们配置,其中resultMap和之前的配置方式一致,主要是匹配存储过程返回的结果列:

    代码
      <resultMaps>
        
    <resultMap id="ResultPerson" class="TestPerson">
          
    <result property="Id" column="Id" />
          
    <result property="FirstName" column="FirstName" />
          
    <result property="LastName" column="LastName" />
          
    <result property="BirthDate" column="BirthDate" />
          
    <result property="WeightInKilograms" column="Weight" />
          
    <result property="HeightInMeters" column="Height" />
        
    </resultMap>
      
    </resultMaps>

     接着就是parameterMap配置,

    代码
    <parameterMaps>
        
    <!--注意:parameterMap中的参数个数和顺序要和ProcGetPersonByName存储过程中的一致-->
        
    <parameterMap id="ParamSelect" class="TestPerson">
          
    <parameter property="FirstName"/>
          
    <parameter property="LastName"/>
        
    </parameterMap>
    </parameterMaps>

     必须注意:parameterMap中的参数个数和顺序要和存储过程中的一致
    在cs中调用如下:

    代码
            public IList<TestPerson> GetPersonsByName(TestPerson model)
            {
                IList
    <TestPerson> list = SqlMap.QueryForList<TestPerson>("SelectByName", model);
                
    return list;
            }

     2、更新类型
    a、插入
    插入成功之后,我们要返回一条记录对应的自增长的主键,存储过程如下:

    代码
    USE [Northwind]
    GO
    CREATE  PROCEDURE [dbo].[ProcInsertPerson] 
        
    @FirstName varchar(50),
        
    @LastName varchar(50),
        
    @BirthDate datetime,
        
    @Weight float,
        
    @Height float
    AS
    BEGIN
        
    INSERT Person
        (
            PER_FIRST_NAME,
            PER_Last_NAME,
            PER_BIRTH_DATE,
            PER_WEIGHT_KG,
            PER_HEIGHT_M
        )
        
    VALUES
        (
        
    @FirstName,
        
    @LastName,
        
    @BirthDate,
        
    @Weight,
        
    @Height
        )
       
    -- 返回最新主键  
       SELECT @@IDENTITY AS value 
    END

     在cs中调用如下:

    代码
          public int CreateByProc(TestPerson person)
            {
                
    int id = 0;
                
    object obj = SqlMap.Insert("InsertPersonByProc", person);
                SqlMap.BeginTransaction();
                SqlMap.CommitTransaction();
                
    if (obj != null)
                {
                    id 
    = int.Parse(obj.ToString());
                }
                
    return id;
            }

     需要注意的是,插入类型的存储过程必须有最后这一句 “SELECT @@IDENTITY AS value”。您可以将它注释掉测试一下。在笔者这里测试的结果就是,在Insert,Update和Delete类型的存储过程中,如果没有output参数或者其他特定返回值的处理,SqlMap的Insert,Update和Delete执行存储过程的返回值始终是-1.
    b、更新
    正像我们测试的那样,执行Update类型的存储过程默认的返回值始终是-1,对于程序员而言,字面理解也就是存储过程所影响的数据表的行数是-1,这显然与我们实际的影响不一致(根据id更新,所以这个存储过程执行一次影响1条或者是0条记录),所以它返回的值至少应该不是-1。我们可以改进的方法是每执行一次更新存储过程,让它返回一个整数值比如1,表示存储过程执行成功。
    so,改进后的存储过程如下:

    代码
    USE [Northwind]
    GO
    CREATE    PROCEDURE [dbo].[ProcUpdatePersonAndOutput] 
        
    @ReturnValue int output,
        
    @Id int,
        
    @FirstName varchar(50),
        
    @LastName varchar(50)
    AS
    BEGIN
    UPDATE Person
    SET
        PER_FIRST_NAME 
    = @FirstName,
        PER_Last_NAME 
    = @LastName
    WHERE PER_ID=@Id
    SET @ReturnValue=1
    END

     在调用这个存储过程的时候,如果要取得返回值,一种合理的写法是下面这样的:
    在xml文件的statements节点中配置如下:

        <!--调用更新类型的存储过程-->
        
    <procedure id="UpdatePersonByProcAndOutput" parameterMap="ParamUpdateOutput" >
          ProcUpdatePersonAndOutput
        
    </procedure>

     parameterMap的配置:

    代码
        <!--输出output参数  必须设置为HashTable或者HashTable的父类接口-->
        
    <parameterMap id="ParamUpdateOutput" class="IDictionary">
          
    <parameter property="ReturnValue" column="ReturnValue" direction="Output" />
          
    <parameter property="Id"/>
          
    <parameter property="FirstName"/>
          
    <parameter property="LastName"/>
        
    </parameterMap>

     cs文件中调用如下:

    代码
            /// <summary>
            
    /// 存储过程的output 参数返回
            
    /// </summary>
            
    /// <param name="person"></param>
            
    /// <returns></returns>
            public int UpdateAndGetOutput(TestPerson person)
            {
                
    int i = 0;
                Hashtable htParam 
    = new Hashtable();
                htParam[
    "ReturnValue"= i;
                htParam[
    "Id"= person.Id;
                htParam[
    "FirstName"= person.FirstName;
                htParam[
    "LastName"= person.LastName;
                i 
    = SqlMap.Update("UpdatePersonByProcAndOutput", htParam); //这里还是-1
                i = (int)htParam["ReturnValue"];//这里才是最后的返回值
                return i;//返回值1
            }

     ps:在cs中获取返回值我已经注释的很清楚,对于output参数,网上已经有人提出取不到返回值,解决的方法您可以参考这一篇这一篇。本文的示例测试已经通过。
    c、删除
    删除是按照id删除一条记录,但是这里的示例我们还是按照类的方式作为传值参数,您可以把参数改成整数的形式。示例代码我就不贴了,文章最下面我会提供demo下载,所有的存储过程都在IBatisNetDemo的Script文件夹下。
    ps:近一阶段忙于项目,iBatis.net的学习也搁置了。现在回看这篇真是木有技术,竟然花了这么长时间,杯具鸟啊。
    demo下载地址:demo

  • 相关阅读:
    scp常用操作指令
    php 5.6.36 安装mcrypt
    记https在Android浏览器无法访问
    centos 7 源码包安装、卸载nginx
    Linux进程守护——Supervisor 使用记录
    Nginx日志切割工具——logrotate 使用记录
    计算机相关网段计算
    PHP链接sqlserver出现中文乱码
    Yii2 init 与 beforeAction 区别
    利用yii2分页插件,成对取出数组数据
  • 原文地址:https://www.cnblogs.com/jeffwongishandsome/p/1543219.html
Copyright © 2011-2022 走看看