iBatis.Net(5):Data Map(了解)

总算,总算,能写点示例啦,呵呵,其实前面的几篇,我感觉自己写的也很生硬,没有Demo理解起来是很困难,很多名词,反正我初次接触iBatis的时候,是一点也不理解的,我也是比较习惯与从示例中学习的,到今天这一篇,终于可以完成一个可以让iBatis真正运行起来的实例啦,前面的,可能只能理解为纸上谈兵,不过之所以这么设计,也是不得意而为,因为你不从本质上了解它的协作过程,不会把这个框架运用的很好的

这一篇要写到的,就是我们所有的查询语句的定义,DataMap,它也是定义在xml文档里的,的确iBatis.Net没有像nhibernate和linq to sql那样,不需要写sql语句,不过也正是因为在这里我们还是需要写sql语句,才更好的说明了iBatis.Net的特性,或者说叫优势,这里说这些可能您还不懂得这个优势到底体现在哪里,看完这篇文章,我觉得您一定会觉得略微猥琐的爱上它的,哦,突然想起来,有朋友在我上一篇的留言里说,让我把iBatis.Net和nhibernate对比的写一下,我如果有时间,会写一些关于nhibernate的文章的,但是,我还是觉得,您如果真想了解这两个框架的优劣势,还是先把这两个框架都研究个差不多,然后自己去体会他们的差距和优劣势比较好,我可能对某一种框架的某种特性有特别的偏爱,而可能您却不以为然或者您一点也不这么觉得这个特性会带来多少的方便,所以,差距在哪,您还是需要身体力行的自己去观察,去体会。。。。好了  闲话少说,书归正传吧

这一节的所有实例使用到的数据库,还是我们经典的NorthWind,如果您还没有这个示例的数据库的话,我会在这篇文章结束后添加一个下载,包括我这一节所有的示例源码

首先为了可以使用到一些常用的配置项,我们需要新建一个项目,专门用来存放数据实体类,当然这是一个很不好的做法,但是,这只是个示例,您在实际操作的时候千万别这么做,我推荐的做法是,把对于一个使用到当前实体类的所有操作代码,以方法的形式分解开,然后全部放在这个实体类里,这样可以有效的避免耦合

iBatisSample是我创建的一个c#控制台应用程序,Domain是我创建的一个类库项目,在这个项目里创建一个Customers类,我想我不说您也可以知道它的内容啦,不过我还是把这个类和我们需要映射到的数据表结果展示一下:

Customers类:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Domain
{
    public class Customers
    {

        public string CustomerID { get; set; }

        public string CompanyName { get; set; }

        public string ContactName { get; set; }

        public string ContactTitle { get; set; }

        public string Address { get; set; }

        public string City { get; set; }

        public string Region { get; set; }

        public string PostalCode { get; set; }

        public string Country { get; set; }

        public string Phone { get; set; }

        public string Fax { get; set; }
    }
}

数据库中的Customers表结构:

当然,我这里为了方便,就使用了相同的字段名称,当然您完全可以不这么做,包括类的名称也是,继续看下去就明白了,

我们创建一个叫做Test.xml的文档

<?xml version="1.0" encoding="utf-8" ?>
<sqlMap namespace="its" xmlns="http://ibatis.apache.org/mapping" xmlns:xls="http://www.w3.org/2001/XMLSchema-instance">
  <statements>
    <select id="SelectAllCustomers" resultClass="Domain.Customers">
      Select * from Customers
    </select>
  </statements>
</sqlMap>

这里我有生以来见过的最简单的iBatis示例啦,先不对它做任何解释,如果我们要使用它,还需要在SqlMap.config中添加对它的引用

<sqlMaps>
    <sqlMap resource="../../Maps/Test.xml"/>
</sqlMaps>

这样,我们就可以在我们的程序代码里这样使用它

ISqlMapper mapper = Mapper.Instance();
IList<Customers> customers = mapper.QueryForList<Customers>("SelectAllCustomers", null);
foreach (Customers customer in customers)
{
     Console.WriteLine(customer.CustomerID+" | "+customer.CompanyName);
}

Console.ReadKey();

.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }

运行,如果你的各种配置没有错的话,那么就可以输出整个Customers表里的数据啦,当然,这种第一次成功的的情况太少了,原因之一也是因为iBatis.Net的这个错误的机制还是有点问题的,实话说,我在第一次运行iBatis程序到得到结果之间的调试绝对超过半个小时,这也是我一直强调,不要着急示例,一定要充分的了解它再使用它的一个原因

然后,我再解释一下整个程序(虽然破烂不堪)的运行过程,首先通过Mapper.Instance()获取DataMapper实例,然后通过DataMapper提供的API  QueryForList<Customers>()方法,得到一个泛型化的列表,因为我们在映射文件中定义的是Customers表中所有的数据,然后通过这个Select节点的resultClass定义返回数据的实体类型,就是我们一开始定义的那个Customers列,因为这个类的属性都是与数据表中的列名和数据类型对应的,所以可以正常的实例化一个个的Customers实例,并且添加到列表中

但是,这里有个问题,在我们的映射文件中使用的resultClass为一个比较长的字符串,它实际上是一个类的完全限定名,虽然这个长度我们还暂时可以接受,但是如果像DataAccess.SqlServer.NorthWind.Domain.Customers这样长的名称,难道您还真打算一次一次的敲碎键盘为止嘛,您可能说可以复制粘贴啊,但是如果我们在复制粘贴了200份后,因为某些原因,这个类的位置有改动,您又将作何感想,所以,这里就需要使用到一个指定别名的方式,对我们上面的Test.xml做一下修改

<?xml version="1.0" encoding="utf-8" ?>
<sqlMap namespace="its" xmlns="http://ibatis.apache.org/mapping" xmlns:xls="http://www.w3.org/2001/XMLSchema-instance">

  <alias>
    <typeAlias alias="Customers" type="Domain.Customers"/>
  </alias>
  <statements>
    <select id="SelectAllCustomers" resultClass="Customers">
      Select * from Customers
    </select>
  </statements>
</sqlMap>

聪明的您一定看到的效果,我就不解释了,这个方式很好的解决了我上面的“刁难”

但是,小白总是刁难不断的人,现在又有了一个问题,如果我们的数据实体类已经定义好了,并且已经在很多地方使用,这个时候更改它是绝对不可能的啦,但是我们数据库中的列名与数据实体类中的属性名称却不对应,这个时候,我们就需要借助一个resultMap的东西,我们把上面定义的Customers中的属性名CustomerID改为CustomerIdent,我们修改Test.xml映射文件

<?xml version="1.0" encoding="utf-8" ?>
<sqlMap namespace="its" xmlns="http://ibatis.apache.org/mapping" xmlns:xls="http://www.w3.org/2001/XMLSchema-instance">

  <alias>
    <typeAlias alias="Customers" type="Domain.Customers"/>
  </alias>

  <resultMaps>
    <resultMap id="Customer" class="Customers">
      <result property="CustomerIdent" column="CustomerID"/>
      <result property="CompanyName" column="CompanyName"/>
      <result property="ContactName" column="ContactName"/>
      <result property="ContactTitle" column="ContactTitle"/>
      <result property="Address" column="Address"/>
      <result property="City" column="City"/>
      <result property="Region" column="Region"/>
      <result property="PostalCode" column="PostalCode"/>
      <result property="Country" column="Country"/>
      <result property="Phone" column="Phone"/>
      <result property="Fax" column="Fax"/>
    </resultMap>
  </resultMaps>
  
  <statements>
    <select id="SelectAllCustomers" resultMap="Customer">
      Select * from Customers
    </select>
  </statements>
</sqlMap>

在修改过的映射文件中,我们没有使用resultClass直接指定一个实体类,而是指定了一个我们定义的名为Customer的resultMap,在这个resultMap中,我们定义了所有返回列和所有数据实体类中属性的映射关系,这样就解决了我们上面的问题

那么,这是查询,插入、更新、和删除呢,我们应该怎么做?

插入

<insert id="InsertOneCustomer" parameterClass="Customers">
      Insert into Customers
      (CustomerID,CompanyName,ContactName)
      values
      (#CustomerIdent#,#CompanyName#,#ContactName#)
    </insert>

更新

<update id="UpdateOneCustomer" parameterClass="Customers">
      Update Customers set CompanyName=#CompanyName# where CustomerID=#CustomerIdent#
    </update>

删除

<delete id="DeleteOneCustomer" parameterClass="Customers">
      Delete from Customers where CustomerID=#CustomerIdent#
    </delete>

这一篇先写这么多,关键是让您可以有一个基础的认识,当然,DataMap的内容远远不止这些,其实到现在,也没有真正的让大家感觉到它的优势在那里,只是让大家体验一下它整个的协作过程和一些基础的定义该怎么写,下一篇,我将会详细的介绍映射文件的内容和一些技巧性的东西,如果有可能的话,我想最晚不会超过今天,也希望对iBatis有兴趣的朋友继续关注吧

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Golang语言社区

亲身经历的痛--database/sql: Stmt的使用以及坑

前言 众所周知,golang操作数据库,是通过database/sql包,以及第三方的实现了database/sql/driver接口的数据库驱动包来共同完成的...

50010
来自专栏草根专栏

使用静态基类方案让 ASP.NET Core 实现遵循 HATEOAS Restful Web API

Hypermedia As The Engine Of Application State (HATEOAS) HATEOAS(Hypermedia as t...

3815
来自专栏更流畅、简洁的软件开发方式

Attribute(特性),怎么用才更好?

前几年:   2008年的某一天,我坐火车去北京。硬卧上铺,一晚上就到北京了。爬到上铺之后发现,旁边上铺有一老兄抱着一个笔记本,一开始还以为是看电影呢,仔细一...

2339
来自专栏安富莱嵌入式技术分享

【二代示波器教程】第15章 FreeRTOS操作系统版本二代示波器实现

本章教程为大家讲解FreeRTOS操作系统版本的二代示波器实现。主要讲解RTOS设计框架,即各个任务实现的功能,任务间的通信方案选择,任务栈,系统栈以及全局变量...

711
来自专栏刘望舒

Android解析WindowManagerService(一)WMS的诞生

前言 此前我用多篇文章介绍了WindowManager,这个系列我们来介绍WindowManager的管理者WMS,首先我们先来学习WMS是如何产生的。本文源码...

2806
来自专栏dotnet core相关

讲一下Asp.net core MVC2.1 里面的 ApiControllerAttribute

ASP.NET Core MVC 2.1 特意为构建 HTTP API 提供了一些小特性,今天主角就是 ApiControllerAttribute. (注:文...

982
来自专栏博客园

讲一下Asp.net core MVC2.1 里面的 ApiControllerAttribute

转自:https://www.cnblogs.com/sheldon-lou/p/9495377.html

712
来自专栏不止是前端

实用主义:Promise让异步回调更加优雅

3328
来自专栏瓜大三哥

FSMC与FPGA通信

STM32是ST(意法半导体)公司推出的基于ARM内核Cortex-M3的32位微控制器系列。Cortex-M3内核是为低功耗和价格敏感的应用而专门设计的,具有...

703
来自专栏ImportSource

一次与印度兄弟就Java10中的Thread-Local Handshakes的探讨

背景 Java10引入了Thread Local Handshake功能。对此功能本人看了JEP312以后还是没有一个比较清晰的认识。为此,问了一些国内的JVM...

3979

扫码关注云+社区