iBatis详细使用手册

iBatis详细使用手册
iBatis详细使用手册

目录

系列(1) 总览..................................................错误!未定义书签。系列(2) 配置运行环境和日志处理................................错误!未定义书签。系列(3) 映射文件基础..........................................错误!未定义书签。系列(4) iBatisNet API基础....................................错误!未定义书签。系列(5) ParameterMap ..........................................错误!未定义书签。系列(6) ResultMap .............................................错误!未定义书签。

系列(1) 总览

学习和使用Ibatisnet已经有一段时间了,前段时间也有写过一些与iBatis相关的Blog。也答应过一些朋友要比较全面地介绍一下iBatis,分享自己的学习过程和使用经验,记录一些常见且容易出现的问题。但由于前段时间一直在准备考试,而且当前的项目时间进度也比较紧,所以一直迟迟未能开始,在这里表示歉意,希望现在开始不会晚。不过最近社区(博客园)好消息不断,我发现越来越多的人开始关注iBatis了,并且也有热心网友在极力推广,如果您已经对它已经有一些了解了,那么更推荐您去阅读ShanYou的文章,他写的文章可能更加适合您。我本人也是一名初学者,这里记录的一些东西可能不会有很多的理论知识(理论知识还不够扎实),更多的可能是突出自己学习过程中需要很长时间来解决的一些问题,或者是个人认为特别重要,并且容易忘记的细节。水平有限,出现错误在所难免,如在这过程中不当之处敬请愿谅,并请不啬赐教。

废话一翻后,进入今天的正题。今天的主题是Introduction,非官方正式介绍的中文版,更多详细的介绍请参阅官方文档。我们要使用它就必须要知道它是干什么用的,能为我们做哪些工作,开发效率如何,执行效率如何,技术难度怎么样。

提到iBatis,大家可能会与ORM技术联系起来。是的,没错,它与ORM技术有一定程度上的联系,但是更确切地讲,它并不是一种很正统的ORM解决方案。因为它不像NHibern ate那样,具备全自动的数据操作,包括查询,插入,更新,删除;也没有像它那样,与数据库的约束关系有紧密的联系(对NHibernate的了解不多,如果有不妥之处,希望能留下你们的臭鸡蛋,等着下回用)。iBatis为我们提供了一种更为灵活的方便的可控的方式去实现类ORM的解决方案。我们需要自己来控制SQL语句,这样做有好处在于,我们可以更灵活地根据我们的需求,编写更加具备性能,功能优势的SQL语句,但它的缺点同样明显,我们还是需要管理和编写SQL语句。但是值得感到高兴的是,我们只需要提供这些SQL语句,和为它提供它所需的参数外,接下来的事情就无需我们参与了。这也是iBatis最核心的功能,也是它为我们所做最多的工作了。根据配置好的SQL语句和参数条件,它会动态生成一

条可执行的SQL语句,然后根据具体传进来的参数值,为这些SQL参数提供不同的具体值。然后根据配置好的数据访问驱动,自动为DbCommand添加DbParameter,自动执行SQL语句,使用IDataReader返回出数据集,生成并返回一个或多个强类型数据类对象(数据集用ILi st集合对象表示)。我曾经在Community Server中也见过类似的返回强类型数据对象的实现,但是需要很多的代码,与直接返回DataTable相比,重复代码会更多。所有的这些在i Batis中,只需要提供一个配置文件,调用它提供的SqlMapper实例对象中的方法就可以很简单容易地实现了。当然你也许会说,那这样如果系统比较大的话,可能就需要很多的配置文件了。是的,又陷了另一个极端了。怎么办呢?没办法,鱼和熊掌不能兼得啊。这里还不得不重点强调一下,如果你是经常在存储过程中拼接SQL语句的话,那我就更加推荐你马上就开始使用iBatis吧。

提到数据操作,就不能不提到数据的安全性和完整性问题了,也就是数据操作的事务问题。如果你是直接使用进行事务操作的话,那您可能需要写更多的代码了,当然我们可以使用E nterprise Library来简化我们的工作。那现在通过一段简单的代码也看一下在iBatis中该如何实现事务吧:

:可以根据需要配置一些常量属性。如果这些属性有很多的话可以单独写一个文件里面,再通过resource(或url, embedded分别是引用url和编译在程序中的资源文件)属性引用进来。如:

这个配置节是可选的。

2. settings:包括有三个配置段:

useStatementNamespaces:在文档中说明它的作用是配置在使用语句ID的时候要不要加命名空间,例中${useStatementNamespaces}就是使用properties中的一个属性,默认是false。

cacheModelsEnabled 是配置要不要启用iBatis的缓存模型,默认是true。

validateSqlMap 是配置要不要启示验证映射文件,默认是false。

3. providers :配置数据驱动提供类配置文件的路径和文件名。

4. database :数据库的信息,包括使用哪些数据库驱动和数据连接字符串的配置。

5. alias :类型别名的配置,为了使用更方便的使用类(类名更短),就需在这里进行别名的配置。

6. typeHandlers :这个就相对比较复杂些了,到目前我也没有使用到。从字面上理解,它是一个类型的处理器,它的作用是当你使用的数据库当中有iBatis不支持或不认识的字段(或者不希望默认的处理方式),那就可以为它取一个名字,并且指定对应的.NET 类型来处理它。

7. sqlMaps :用来包含当前已经写好的,并且需要用到的数据类映射文件。

以上就是的基本内容了。注意,以上凡是涉及到引用外部文件的都支持resouce,url,embedded 三种方式。

的配置类很简单,在默认的中已经有很多不同数据库的数据驱动,而在的database配置的provider属性就是使用中已有的不同驱动中的一个。以下是添加一个数据访问驱动:

OK,以上就是和的基本内容。下面我来介绍一下如果利用log4net来记录iBatisnet的一些运行日志记录。这也是我当初花了很多的时间才解决的一个问题,因为记录这些日志太重要了,它可以记录下每次生成并执行的SQL语句,对我们排除配置错误有非常重大的意义。而如果你是使用最新版的(当前是),但是文档使用的是的话,那可能你怎么折腾都无法搞出结果来。

按照的文档介绍那样在加上合适的配置节后,然后把和拷到bin目录下后,你可能会认为跟文档介绍的一样,生成一个,并记录下日志。但事实不是这样的,在的版本中还需要再加上一个配置节组:

配置组的配置值如下:

经过以上的配置后,再运行程序,就会创建并且记录日志了。注意:即使是按以上的配置后,有可能还是无法记录日志,那就可能是和的中的一个或两个没有拷到bin目录,正常情况下,我们不需引用这两个程序集,只需把它们拷到运行目录下,即使你需要记录日志,但找不到他们,程序仍然能正常执行而不会抛出异常,如果你没有经验的话,解决这个问题可能需要你很多的时间。

以上就是今天要介绍的内容了,Hope this helps。

附注:

1.参考资料:Data Mapper ;2.配置文件智能提示:把三个文件拷贝到VS 2005 :C:\Program Files\Microsoft Visual Studio 8\Xml\Schemas (安装目录) VS 2003 :C:\Program Files\Microsoft Visual Studio .NET 2003\Common7\Packag es\schemas\xml (安装目录)下,就可以在VS IDE下编写配置文件时得到Intellise nse的帮助,前提是配置的文件的第一个节点写正确的命名空间和XSD文件。

系列(3) 映射文件基础

iBatis的核心就在于映射文件(Data Map XML File)。在映射文件里可以定义包括要执行各种SQL语句,存储过程,输入参数映射,返回结果映射,缓存机制,并且能通过几种相对比较复杂的配置实现对象之间的关联关系和延迟加载。这也是iBatis区别ORM框架的,具备更灵活性,更高性能的关键所在。

配置文件可以写得很简单,也可以很复杂。复杂配置文件也是出于更好的设计,更好性能,更好扩展性方面的目的。再复杂的配置文件也是有限的,一个映射文件包括:Mapped Statements、Parameter Maps、Result Maps、Cache Models几个主要的配置,还包括命名空间的配置,类型别名(前一篇中有介绍)的配置。

1.Mapped Statements :顾名思义就是映射的语句声明。它是整个iBatis配置核心的核心,真正将被执行的SQL语句(或存储过程)都是必须在这里被显式声明。在Mapped St atements里可以包含有:statement、select、insert、update、delete、procedure这6种不同的语句类型。从词面理解相信就可以了解到这些类型功能的一大半了。statement可以包含所有类型的SQL语句(存储过程),它是一个泛泛的语句配置,没特别明确的职责,相反,其它5种类型的语句配置就是专门负责各种不同的SQL语句。下面这张图列出了各种类型的语句的不同职责和调用方法。

图片看不清楚?请点击这里查看原图(大图)。

2.Parameter Maps :参数映射的配置,它是被用来向一个语句(statement)提供所需参数的配置。每一个Parameter Maps都有一个自己的ID,在需要的时候需要在statement 的 parameterMap属性中提供它的ID。但是对一个语句来说,它并不是必须,在iBatis中还支持内联参数(Inline Parameter Maps)的形式,我们不需单独写一个Parameter Maps

配置,只需要向parameterClass提供参数的类型,可以是元数据类型,复合数据类型,ID

ictionary数型的弱类型对象(使用key,value的键值对)。在内部访问数据类型的时候只使用#property#的形式访问对应的属性值。

注意:在任何地方使用到的parameterClass类型如果是一个元数据类型(int,string etc),都需要使用#value#的形式的来访问它的值。

3.Result Maps :返回结果的映射关系配置,就是列与属性的对应关系。在statemen t中使用resultMap属性来指定一个结果映射。对一个statement来说,resultMap也不是必须的,同样的,它仍然可以被resultClass给代替,因为如果返回出结果数据集的列名跟数据对象的属性相同的话,它会自动去匹配,但是它不保证所有列都被会被正确映射(当某列名在对象中找不对应的属性名,这列值将不被处理)。而resultMap则不同,如果已经在resultMap中定义将要使用到列或属性在结果集或数据对象中不存在,将会被认为是错误的,将会抛出异常。通过上面的表可以看到insert,update,delete三种语句类型是没有re sultMap和resultClass,因为原则上来说,它们的操作是没有必要返回结果集。

注意:如果在一个statement中同时指定了resultMap和resultClass属性的话,那将会优先使用resultMap。同时result Map也是一个实现对象复杂查询功能的重要手段,如:result map的继承(与discriminator配合使用),对象的1..1、1..N关系查询。

4.Cache Model :缓存模型。使用在Cache Model中定义好的缓存机制,只需在查询语句配置的cacheModel属性就可以很容易地缓存查询返回的数据集。在iBatis中提供了三种的类型的缓存模式(Memory,LRU,FIFO)算法。三种算法主要在于静态过期策略上的不同,而它们都有相同的动态过期依赖策略,即可以设置执行哪些statement时,缓存过期。

注意:iBaits的缓存模型正常情况是非常好用的,但是因为缓存过期策略上的封装性,它在多个服务器,负载平衡场景下还是有它的局限性。

系列(4) iBatisNet API基础

有了对iBatis配置系统的一些认识后,现在就先来简单了解一下,iBatis是通过什么的方式去调用映射文件的SQL语句的。这对我们接下来深入了解有很大的帮助。

对于简单的iBatis应用场合来说,我想大部分都是集中在与SqlMapper对象打交道。这个类应该说是一个工具类,因为我们一般都是直接调用这个类的方法去执行QUID操作,但是它却不是真正的去做这些事情。因为iBatis内部有很多的类,对象之间的关系是非常复杂的,如果让客户直接去使用它内部方法,无疑增加了使用的复杂性,同样也会产生很多的冗余代码。因此这里它使用外观设计模式,通过SqlMapper类封装了iBatis执行数据库访问的复杂操作,包括打开一个会话(Session),获取返回IMappedStatement对象实例,执行数据库访问,关闭连接等相关操作。这样我们在使用iBatis API的时候就可以非常简单调用的一个方法,就可以做所有的事情了。比如查询接口public IList QueryForList(str ing statementName, object parameterObject),它的内部实现代码是这样的。

那这些代码如果直接在客户代码中去实现,可想而知工作量会有多大。并且还法保证正确性。

以上简单看了一个SqlMapper的作用,那该怎样实例化这个对象呢?实例化它也是一个非常简单的事情。在iBatisNet中,SqlMapper对象默认是一个单件模式的实现。通过Map per类的静态Instance属性来实例化一个SqlMapper对象。这样的设计可能有一部分是出于性能方面的考虑。因为在初始化SqlMapper对象,需要初始iBatis运行环境配置,读取和初步解析包含的各个映射文件,所以在在系统运行时第一次调用iBatisNet API的时候,可能会需要比较长来处理这个配置。属性的实现如下:

所以在使用API的时候可以像下面的这么简单:

当然,如果愿意而且有必要的话,也完全可以由自己来实例化这个对象,我们可以直接使用DomSqlMapBuilder,它为我们提供这样的扩展能力,通过它的多种实例方法都可以返回出SqlMapper对象:Build,Configure,ConfigureAndWatch。在需要用到多个数据库或是多种不同数据库类型的场合下,这种方法是非常有用的。

注意:在使用一个接口时,使用的statementName要在对应类型的statement类型。比如在使用Insert接口时,如果你指定的是一个select类型配置语句的话,那将会抛出异常。因为每一种statement类型都对应一种类型,比如如select 类型的配置语句对应的是Se lectMappedStatement类,它是从MappedStatement继承下来,而它的ExcuteInsert方法是这样实现的

这样就保证了每一种语句类型的职责明确。

系列(5) ParameterMap

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

在配置文件中:

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

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

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

对于下面这个配置:

它所使用的ParameterMap配置如下:

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

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

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

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

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

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

相关主题
相关文档
最新文档