译注:本章讲解的是iBATIS的安装和配置,原书使用的是Java版本,与.NET版本的安装、配置过程不尽相同,因此这里直接就.NET版本进行说明。主要参考的是iBATIS官方的DataMapper Guide文档,本章的配置主要针对DataMapper,DataAccess的配置将出现在第10章。
iBATIS的安装过程快速而简单。它是一个类库,而不是应用程序,所以实际上并不需要安装,但要在应用程序中使用它还是要经过几个步骤。
如果您熟悉C#和ADO.NET,那么可能需要好好阅读本章为下面的一两章做好准备。首先,我们提供了安装和配置过程的概览,然后是该过程的详细说明。
要获取iBATIS,您有两种选择。可以下载二进制发行包,然后解压缩到一个目录中;也可以从Subversion资源库中获取一份源代码副本,手动生成它。不管采用哪种方式,最终得到的是相同的一组文件。
在得到iBATIS发行包之后,只要将需要的dll文件添加到应用程序引用中即可。
3.1 获取iBATIS发行包
3.1.1 二进制发行包
这是最快速、简单的方式。iBATIS已经预先生成好了,您只需要下载,解压缩,然后开始使用。
注意:iBATIS的二进制发行包可以在http://ibatis.apache.org/dotnetdownloads.cgi下载(这里可以下载到dll文件,源代码,实例和文档)。
3.1.2 由源代码生成
如果您有兴趣增强框架,修复bug,或者只是想通过亲自编译来了解您所得到的内容,那就可以从Subversion资源库获取一份副本,由源代码生成。第12章中我们将深入了解扩展iBATIS框架的细节,因此本节内容会比较简单,不过这些也足够您开始使用了。
注意:这里提到的Subversion(SVN)资源库是所有新的Apache项目使用的版本控制系统。Subversion是CVS的替代品。SVN的目的在于提供一个环境,使得在框架发生变化时,不用担心丢失源代码(因为每个开发人员都有一份副本,同时服务器上也存有多份拷贝)。
如果您希望更多地了解Subversion,可以访问它的主页http://subversion.tigris.org/。
iBATIS的Subversion资源库地址为:http://svn.apache.org/repos/asf/ibatis/trunk/。
3.2 发行包的内容
如果您获取的是源代码,那么会得到一个VS解决方案和几个C#项目。在source文件夹下有8个文件夹,构成了iBATIS.NET发行包。它们是:
Folder Name
|
Description
|
External-Bin
|
iBATIS项目所需的依赖项程序集。
|
IBatisNet.Common
|
该程序集包含了DataAccess和DataMapper所共用的类。
|
IBatisNet.Common.Logging.Log4Net
|
Log4Net工厂适配器类。
|
IBatisNet.Common.Test
|
IBatisNet.Common的测试项目,可用于NUnit。
|
IBatisNet.DataAccess
|
Data Access Objects框架。
|
IBatisNet.DataAccess.Extensions
|
包含一个C#项目,用于对DataAccess框架的扩展,如对NHibernate的支持。
|
IBatisNet.DataAccess.Test
|
DataAccess框架的测试项目,可用于NUnit。
|
IBatisNet.DataMapper
|
DataMapper框架。
|
iBatisNet.DataMapper.Test
|
DataMapper的测试项目,可用于NUnit。
|
您可以加载IBatisNet.2005.sln,生成所需的程序集。解决方案中有7个项目,应当能够顺利通过编译。我们需要的程序集位于\IBatisNet.DataMapper\bin\Debug下。创建的程序集是:
DataMapper有一个外部依赖项:
该dll在External-Bin文件夹中。
3.3 依赖项(略)
3.4 将iBATIS添加到应用程序
切换到您自己的应用程序,打开要使用DataMapper的项目。取决于解决方案的组织方式,项目有可能是Windows或Web应用程序,也可能是类库项目。这样可能需要项目添加一到两个引用:
如果您使用的Mapper单例(singleton),那么唯一需要引用的是DataMapper程序集。IBatisNet.Common和Castle.DynamicProxy在运行时是需要的,但VS.NET会帮您解析这些依赖关系。如果使用Data Access Objects框架,那么还需要添加对DataAccess的引用。
如果您已经按前面说过的方式生成了iBatisNet,那么需要的三个程序集(IBatisNet.DataMapper.dll,IBatisNet.Common.dll,Castle.DynamicProxy.dll)都在DataMapper项目的bin\Debug目录下。
3.4.1 添加XML文件项
在添加了对程序集的引用后,下一步是向项目(可能是Windows,Web应用程序,类库或测试项目)中添加三种类型的XML文件。这些文件是:
不难理解,SqlMap.config和providers.config文件应放在DataMapper运行时可以找到的地方。这两个文件的默认位置取决于项目的类型, 如下表所示:
Windows应用程序,类库,测试项目(使用NUnit或其它等价工具)
|
二进制文件夹(如/bin/debug),.dll和app.config所在目录
|
Web应用程序
|
在程序根目录,即web.config所在处
|
3.4.2 与VS.NET集成
每一个配置文件(SqlMap.config,SQL 映射文件,providers.config)都与一个XML Schema文件关联。这种关联的好处在于,可以对文档进行验证(在运行时完成),使用编辑器的特性如智能感知/内容自动完成。
要在VS.NET的XML编辑器中的Schema和我们的配置文件之间建立关联,应该将Schema文件(SqlMap.xsd,SqlMapConfig.xsd,providers.xsd)添加到VS.NET项目或者VS.NET安装目录。显然第二种选择会让我们一劳永逸。VS.NET安装目录可能是:
C:\Program Files\Microsoft Visual Studio 8\Xml\Schemas(VS.NET 2005)
或
C:\Program Files\Microsoft Visual Studio .NET 2003\Common7\Packages\schemas\xml(VS.NET 2003)
或
C:\Program Files\Microsoft Visual Studio .NET\Common7\Packages\schemas\xml(VS.NET 2002)。
将Schema文件注册到VS.NET后,我们就可以在VS.NET中享用智能感知和配置文档验证了。
3.5 iBATIS和ADO.NET
对ADO.NET的深入讲解已经超出了本书的范围,但我们将从一个较高层次进行分析,以为本书的其它部分提供一个基础。
微软的ADO.NET的API是.NET中数据库连接的标准。ADO.NET定义了一组接口,数据库提供商需要为其数据库产品提供接口的实现(Provider),否则,开发人员无法使用,人们认为提供商的封闭是应该避免的反模式(anti-pattern)行为。
3.5.1 释放ADO.NET资源
在使用ADO.NET时,容易发生获取资源,然后却忘记了正确地释放资源的问题。垃圾回收进程最终可能会释放它们,但这需要时间,而且没有保证。如果这些资源没有释放掉,应用程序最终可能会耗尽资源,进而崩溃。iBATIS框架帮助开发人员管理这些资源,从而减轻了开发人员的负担。开发人员不再需要担心资源的分配和释放,而是关注于他们需要的数据。但是,如果愿意,开发人员仍然可以手动地管理这些资源。
3.5.2 SQL注入
另一个常见的问题(在Web应用程序中更易出现)是SQL注入,它使得应用程序不以开发人员所期望的方式执行SQL。如果程序使用字符串拼接来构造SQL语句,但没有正确地过滤参数,恶意的用户传入的参数会改变查询的内容。考虑类似于select * from product where id = 5这样的例子。如果这里的5直接来自用户的输入,然后同select * from product where id =拼接,那么用户可以输入5 or 1=1,从而改变了SQL语句的真实用意。如果用户输入的是5; delete from orders,那就更糟了,SQL语句会乖乖地查询一条记录,然后将orders清空。灵活性也带来了风险,因此如果不正确地使用了iBATIS,我们的程序仍有可能会受到SQL注入的攻击。但是,iBATIS通过使用Parameter提高了程序受到此类攻击的难度(Parameter)。
只有那些使用显式的SQL字符串置换语法的语句是有风险的。考虑下面这个例子,该语句接受动态的表名和列名:
SELECT * FROM $TABLE_NAME$ WHERE $COLUMN_NAME$ = #VALUE#
这种语句在某些情况下很灵活,也很有用,却易受到SQL注入的攻击,因此要慎重使用。这不是iBATIS的问题,这样的语句无论如何执行总会面临这种问题。因此对于那些动态构造的语句,如果会受用户输入的影响,一定要对用户的输入进行验证。
3.5.3 降低复杂性
ADO.NET非常强大,同时也是层次很低的API。为了帮助您更好地理解iBATIS有哪些好处,我们做个比较。(请参看 2.2节 工作原理中的例子)
3.6 iBATIS的配置(continued)
在第2章中,我们简要地浏览了iBATIS的配置(那个例子实在简单,如果您没有阅读那一节内容也不必担心)。在本节中,我们将创建SQL Map配置文件。这个文件是iBATIS的核心,如图3.1所示。
图3.1描述了iBATIS的配置,其中SqlMapConfig文件是一切的核心。
3.6.1 SQL Map配置文件
由图3.1可以清楚地看到,SQL Map配置文件(SqlMap.config)iBATIS配置的核心。从数据库连接到使用的SqlMap文件的相关配置都由此文件提供。
注意:上面说的核心配置文件名称通常为SqlMap.config。尽管它也可以使用其它名称,我们在这里还是遵循约定。
下面的代码清单演示了一个示例配置文件,我们将在后面的章节中进行讨论。
在接下来的几个小节中,我们将讨论SqlMap.config文件的详细配置选项。在接下来的3章(4,5,6)中,我们将探索在SqlMap.xml文件中定义的映射语句(Mapped Statement)。然后在第7章,我们将详细讨论事务管理相关的内容。
3.6.2 <properties>元素
有时,配置文件中的同一个值会出现在多处。通常情况下,我们将程序在服务器间迁移时,某些配置选项的值要进行修改。为了更好地管理这些配置选项的值,我们可指定一个标准的属性文件(含有name=value对),将DataMapper的部分配置转移到其中。在属性文件中的值将成为shell变量,可以在DataMapper配置文件和Data Map定义文件中使用。例如,如果属性文件中包含了
那么在DataMapper配置文件(SqlMap.config)中的任何元素都可以使用变量${UserId}来插入值”sa”。例如:
使用属性文件使生成、测试、部署的过程变得简单。
3.6.2.1 <properties>的特性(attributes)
Attribute
|
Description
|
resource
|
指定要从应用程序根目录加载的属性文件。
<properties resource="properties.config" />
|
url
|
指定属性文件的绝对路径
<properties url="c:\Web\MyApp\Resources\properties.config" /> |
embedded
|
指定要从程序集的资源中加载的属性文件。该特性的语法为’[extendednamespace.]filename, assemblyName’。
|
Attribute
|
Description
|
resource
|
指定要从应用程序根目录加载的属性文件。
resource="properties.config"
|
url
|
指定属性文件的绝对路径
url="c:\Web\MyApp\Resources\properties.config"
-or-
url="file://c:\Web\MyApp\Resources\properties.config"
|
embedded
|
指定要从程序集的资源中加载的属性文件。该特性的语法为’[extendednamespace.]filename, assemblyName’。
embedded="properties.config, IBatisInAction.Ch03Web"
|
key
|
定义一个属性键(变量)名
Key="username"
|
value
|
为指定的属性定义其值。
|
3.6.3 <providers>元素
在ADO.NET中,我们通过Provider来访问数据库系统。对于一个数据库系统,可以使用特定的Provider,也可以使用通用的ODBC Provider。iBATIS的DataMapper使用插件的方式来使用Provider。每一种Provider都表现为一个XML描述元素,位于providers.config中。iBATIS的DataMapper发行包包含了一个标准的providers.config,其中一共有13种Provider元素:
注意:如果您使用的是SQL Server 2005,那么可以打开MARS(Multiple Active Result Set)选项,即设置allowMARS=”true”,并在连接字符串中添加MultipleActiveResultSets=true。
providers.config文件位于DataMapper发行包的根目录。
一种Provider可能会需要您未安装的类库。因此,provider元素提供了enabled特性,这样可以将那些不用的Provider禁用。一个Provider还可以标记为”default”。
标准的providers.config文件中,sqlServer1.1设置为default,sqlServer1.0则被禁用。除了sqlServer1.1,OleDb1.1和Odbc1.1,其它的Provider默认情况下都被禁用了。因此在使用Provider前记住检查一下它的enabled特性值。
重要:如果使用的数据库是MySQL,推荐使用ByteFx Provider。可以从MySQLNet站点(http://sf.net/projects/mysqlnet)下载。如果您可以接受它的license,就可以在项目中添加对其的引用,然后打开ByteFx Provider。
providers.config文件期望的默认位置:
Windows应用程序,类库,测试项目(使用NUnit或其它类似工具) |
程序集文件(dll)所在目录(app.config所在目录) |
Web应用程序 |
程序根目录(web.config所在目录) |
要使用该文件,您可以将其拷贝至期望的默认位置,或者是相对于项目根目录的相对路径,或指定url(绝对路径),还可以作为项目的嵌入资源。如果将其放在期望的默认位置,那么<providers>元素可以省略。
3.6.3.1 <providers>的特性
Attribute
|
Description
|
resource
|
指定providers.config文件相对于应用程序根目录的相对路径。因为根目录因项目类型而有所不同,因此最好使用属性文件来表示相对路径。
resource=”${root}providers.config”
|
url
|
指定providers.config文件的绝对路径。
url="c:\Web\MyApp\Resources\ providers.config" />
-or-
|
embedded
|
指定要从程序集的资源中加载的providers.config文件。该特性的语法为’[extendednamespace.]filename, assemblyName’。
embedded=”Resources.providers.config, MyApp.Data”
|
3.6.4 <settings>元素
Attribute
|
Description
|
cacheModelsEnabled
|
该选项在全局范围内启用或禁用一个DataMapper实例的所有Cache Model。这在调试时可能会很方便。
Example:cacheModelsEnabled=”true”
默认值 :true(启用)
|
useStatementNamespaces
|
如果启用该选项,那么在引用映射语句时必须总是使用完全限定的名称,即Sql Map的命名空间和语句的id。如queryForObject(“Namespace.statementId”);
Example:useStatementNamespaces=”false”
默认值 :false(禁用)
|
validateSqlMap
|
该选项在全局范围内启用或禁用了针对Sql Map文件的校验。这在调试时可能会很方便。
Example:validateSqlMap=”true”
默认值 :false(禁用)
|
useReflectionOptimizer
|
该选项在全局范围内启用或禁用在访问C#对象属性或字段对反射的使用。反射优化器会提供获取、生成、实例化参数和返回结果对象的类型。
Example:useReflectionOptimizer =”true”
默认值 :true(启用)
|
3.6.5 <typeAlias>元素
注意:在iBATIS.NET中,在Data Map定义文件中,我们可以为<alias>元素指定零个或多个<typeAlias>元素。
3.6.5.1 <typeAlias>的特性
Attribute
|
Description
|
alias
|
该元素的唯一性名称。
alias=”Category”
|
type
|
要代替类型的完全限定名称。
type="IBatisInAction.Domain.Category, IBatisInAction.Domain"
|
3.6.5.1.1 type特性
在指定type特性时,它的值必须为下列形式的完全限定类型名称:
比如:
CLR Type
|
Alias
|
System.ArrayList
|
list
|
System.Boolean
|
Boolean, bool
|
System.Byte
|
Byte, byte
|
System.Char
|
Char, char
|
System.DateTime
|
dateTime, date
|
System.Decimal
|
Decimal, decimal
|
System.Double
|
Double, double
|
System.Guid
|
guid
|
System.Hashtable
|
map, hashmap, hashtable
|
System.Int16
|
Int16, short, Short
|
System.Int32
|
Int32, int, Int, integer, Integer
|
System.Int64
|
Int64, long, Long
|
System.SByte
|
SByte, sbyte
|
System.Single
|
Float, float, Single, single
|
System.String
|
String, string
|
System.TimeSpan
|
N/A
|
System.UInt16
|
Short, short
|
System.UInt32
|
Uint, uint
|
System.UInt64
|
Ulong, ulong
|
3.6.6 <typeHandler>元素
<typeHandler>元素用于对自定义类型处理器(Custom Type Handler)的配置。Custom Type Handler扩展了DataMapper的功能,可以处理如下的情形:特定于数据库Provider的类型,数据库Provider未处理的类型,在特定程序中特殊设计。
注意:在Data Map配置文件的<typeHandlers>元素中,可以包含零个或多个<typeHandler>元素。
3.6.6.1 <typeHandler>元素的特性
<typeHandler> 元素有三个特性: Attribute
|
Description
|
type
|
引用要处理类型的名称。
type="guid"
|
dbType
|
指定要处理的dbType。
dbType="Varchar"
如果希望type handler代替iBATIS中默认type handler,那么可以省略该特性。
|
callback
|
Custom type handler类的别名。
callback="GuidVarchar"
|
3.6.7 <database>元素
<database>元素包含与数据库系统配置相关的子元素,它们是<provider>和<datasource>。
3.6.7.1 <provider>元素
3.6.7.2 < datasource>元素
<datasource> 元素指定了 ADO.NET 连接字符串。下面是针对 SQL Server , Oracle , Access , MySql 和 PostgreSQL 数据库的例子。在日常开发中,我们的工作大部分会于Data Map文件相关。这些文件定义了实际的SQL语句和存储过程,其中也包含了参数和返回结果的定义。随着应用程序规模的增大,我们可能会有多个Data Map。为了更好地组织这些Data Map,我们可以创建多个Data Map定义文件,然后在DataMapper配置文件中对它们进行统一引用。对于一个DataMapper实例,它所使用的所有Data Map定义文件都要包含在配置文件中。
下面的例子说明了如何加载(引用)一组 Data Map 定义文件。注意 <sqlMap> 元素是 <sqlMaps> 元素的子元素。
提示:因为应用程序的根目录位置因项目类型而异(Windows,Web或类库),所以在使用<sqlMap>的resource特性时最好使用属性变量(在属性文件中定义)来指定相对路径。将变量定义在一个文件中会更容易维护(注意上面的${projectdir}和${root})。
3.7 小结
安装iBATIS的过程相当简单。在本章中,我们查看了两种获取框架的方法,然后是它的安装和配置。因为iBATIS被设计为简单易用,它的依赖项很少,也容易进行扩展来使用其它工具。
ADO.NET非常强大,同时也是层次很低的API,对其编写可靠(solid)的代码比较困难。使用iBATIS,您可以大大减少面对数据库组件(component)时的复杂性,而更多地关注于业务逻辑。
我们查看了iBATIS配置的一个简单例子——可能是最简单的例子了!在下章中,我们会更详细地讨论如何配置它,还有让它更好地与应用程序集成。
在本章中,我们还查看了iBATIS的配置文件(sqlMap.config)。在使用任何框架的时候,对它的基础有个好的理解都是必要的。本章就是提供了iBATIS DataMapper基础的内容,或者说是给出了一个快速参考文档。
在本章放一张书签吧,当你遇到麻烦时回来看看。如果你在这里没找到答案,那可能需要再到其它章看看了。