iBatis详细使用手册

上传人:s****a 文档编号:120776418 上传时间:2022-07-18 格式:DOCX 页数:29 大小:83.72KB
返回 下载 相关 举报
iBatis详细使用手册_第1页
第1页 / 共29页
iBatis详细使用手册_第2页
第2页 / 共29页
iBatis详细使用手册_第3页
第3页 / 共29页
点击查看更多>>
资源描述
目录iBatis.Net 系列(1) 总览 2iBatis.Net 系列(2) 配置运行环境和日志处理4iBatis.Net 系列(3) 映射文件基础12iBatis.Net 系列(4) iBatisNet API 基础14iBatis.Net 系列(5) ParameterMap 2. 0iBatis.Net 系列(6) ResultMap 2. 4iBatis.Net 系列(1) 总览学习和使用Ibatisnet已经有一段时间了,前段时间也有写过一些与iBatis相关的Blog。也 答应过一些朋友要比较全面地介绍一下iBatis,分享自己的学习过程和使用经验,记录一些 常见且容易出现的问题。但由于前段时间一直在准备考试,而且当前的项目时间进度也比较 紧,所以一直迟迟未能开始,在这里表示歉意,希望现在开始不会晚。不过最近社区(博客 园)好消息不断,我发现越来越多的人开始关注iBatis 了,并且也有热心网友在极力推广, 如果您已经对它已经有一些了解了,那么更推荐您去阅读ShanYou的文章,他写的文章可 能更加适合您。我本人也是一名初学者,这里记录的一些东西可能不会有很多的理论知识(理 论知识还不够扎实),更多的可能是突出自己学习过程中需要很长时间来解决的一些问题, 或者是个人认为特别重要,并且容易忘记的细节。水平有限,出现错误在所难免,如在这过 程中不当之处敬请愿谅,并请不啬赐教。废话一翻后,进入今天的正题。今天的主题是Introduction,非官方正式介绍的中文版, 更多详细的介绍请参阅官方文档。我们要使用它就必须要知道它是干什么用的,能为我们做 哪些工作,开发效率如何,执行效率如何,技术难度怎么样。提到iBatis,大家可能会与ORM技术联系起来。是的,没错,它与ORM技术有一定 程度上的联系,但是更确切地讲,它并不是一种很正统的ORM解决方案。因为它不像NHi bernate 那样,具备全自动的数据操作,包括查询,插入,更新,删除;也没有像它那样, 与数据库的约束关系有紧密的联系(对NHibernate的了解不多,如果有不妥之处,希望能 留下你们的臭鸡蛋,等着下回用)。 iBatis 为我们提供了一种更为灵活的方便的可控的方式 去实现类ORM的解决方案。我们需要自己来控制SQL语句,这样做有好处在于,我们可 以更灵活地根据我们的需求,编写更加具备性能,功能优势的SQL语句,但它的缺点同样 明显,我们还是需要管理和编写 SQL 语句。但是值得感到高兴的是,我们只需要提供这些 SQL语句,和为它提供它所需的参数外,接下来的事情就无需我们参与了。这也是iBatis 最核心的功能,也是它为我们所做最多的工作了。根据配置好的SQL语句和参数条件,它 会动态生成一条可执行的SQL语句,然后根据具体传进来的参数值,为这些SQL参数提供 不同的具体值。然后根据配置好的数据访问驱动,自动为DbCommand添加DbParameter, 自动执行SQL语句,使用IDataReader返回出数据集,生成并返回一个或多个强类型数据 类对象(数据集用IList集合对象表示)。我曾经在Community Server中也见过类似的返 回强类型数据对象的实现,但是需要很多的代码,与直接返回DataTable相比,重复代码 会更多。所有的这些在iBatis中,只需要提供一个配置文件,调用它提供的SqlMapper实 例对象中的方法就可以很简单容易地实现了。当然你也许会说,那这样如果系统比较大的话, 可能就需要很多的配置文件了。是的,又陷了另一个极端了。怎么办呢?没办法,鱼和熊掌 不能兼得啊。这里还不得不重点强调一下,如果你是经常在存储过程中拼接SQL语句的话, 那我就更加推荐你马上就开始使用 iBatis 吧。提到数据操作,就不能不提到数据的安全性和完整性问题了,也就是数据操作的事务问题。 如果你是直接使用A进行事务操作的话,那您可能需要写更多的代码了,当然我们可 以使用Enterprise Library来简化我们的工作。那现在通过一段简单的代码也看一下在iBat is 中该如何实现事务吧:using ( IDalSession session = sqlMap.BeginTransaction()item.Desc ription = newDesc ription;sqlMap.Update(updateItem, item)session.Complete(); / Commit就这么简单的代码,它就会帮我们自动管理事务了。这期间如果出现异常,我们仍然可以捕获到异常信息。OK,通过上面的介绍,我们已经能够了解到一个大概了。总结一下,它帮我们自动管理 和执行SQL语句,并且返回强类型的数据对象。从上面的一段简单的代码中,你可能已经 感觉到了它的使用有多么的简单!并且如果需要的还能够返回生成的DbCommand,支持 我们通过它返回DataTable或者其它的Ado操作返回。但是,这时你会马上产生另一个疑 虑了,我们的工作还是很多啊,比如编写数据类和配置文件,可能工作量并不亚于直接使用 A 返回 DataTable 所写的代码,并且会更加的没有技术含量。所以,对于这些的代码, 我们尽量能通过一些代码生成工具(我是使用CodeSmith )自动生成大部分,然后再根据 我们需要进行修改。再来看看执行效率吧,尽管iBatis或多或少用到反射技术,但由于使用配置文件的形式, 性能影响已经降到最低了。我曾经做过一个测试,用它添加多条记录和使用 UpdateDataSe t 成批提交数据(相同的数据)的方式进行过比较,总体时间效率不会更差,反而会更快一点。最后不得不再提一点,它的缓存机制做得很好,相同的SQL语句,可以根据不同的条 件值,缓存用这个条件执行查询时的输出数据。它的缓存过期策略是封闭的。详细细节,相 信随着深入会有所涉及。对它的介绍就先告一段落了,下一篇将会首先介绍一下它的配置工作环境,重点在于介 绍如何使用 log4net 记录日志。iBatis.Net 系列(2) 配置运行环境和日志处理现在我开始介绍一下 iBatis 的配置和日志处理吧。iBatis基本的运行环境配置主要由两个文件组成,分别是SqlMap.config和Provider.c on fig。它们是必需的两个配置文件,基中SqlMap.co nfig的功能类似于web.co nfig或者ap p.c on fig,是iBatis核心的配置文件,它的存放路径也跟应用程序配置文件一样,必须放在 应用程序的运行目录下并且它的文件名是保留的,不可改变的。而Provider.config是一个 数据驱动提供类的配置,它的文件名是可以随意改变的,因为通过 SqlMap.config 的一个配 置节可以配置它的引用。SqlMap.config 包括以下一些主要的配置节,根据需要,有的配置节并不是必须的:1. properties :可以根据需要配置一些常量属性。如果这些属性有很多的话可以单独写一个文件里面,再通过resource (或url, embedded分别是引用url和编译在程序中的资源文件)属性引用进来。如:这个配置节是可选的。2. settings:包括有三个配置段:vsetting useStatementNamespaces=$useStatementNamespaces/vsetting cacheModelsEnabled = true/ vsetting validateSqlMap=false/useStatementNamespaces:在文档中说明它的作用是配置在使用语句ID的时候要不 要加命名空间,例中$useStatementNamespaces就是使用properties中的一个属性,默 认是 false。cacheModelsEnabled是配置要不要启用iBatis的缓存模型,默认是true。validateSqlMap是配置要不要启示验证映射文件,默认是false。3. providers :配置数据驱动提供类配置文件的路径和文件名。4. database : 数据库的信息,包括使用哪些数据库驱动和数据连接字符串的配置。 vdataSource name=iBatisNetconnectionSt ri ng = /5. alias :类型别名的配置,为了使用更方便的使用类(类名更短),就需在这里进行别名的配置。vtypeAlias alias=ArrayList type = System.Collections.ArrayList,mscorlib/6. typeHandlers :这个就相对比较复杂些了,到目前我也没有使用到。从字面上理解,它是一个类型的处理器,它的作用是当你使用的数据库当中有iBatis不支持或不认识的 字段(或者不希望默认的处理方式),那就可以为它取一个名字,并且指定对应的NET类 型来处理它。vtypeHandle rsvtypeHandler type = bool dbType = Varchar callback=OuiNonBool/7. sqlMaps :用来包含当前已经写好的,并且需要用到的数据类映射文件。vsqlMaps-vsqlMap resource=Mappers/ContentMapper.xml/-v/sqlMaps以上就是Sqlmap.config的基本内容了。注意,以上凡是涉及到引用外部文件的都支持resouce, url, embedded 三种方式。Provider.config的配置类很简单,在默认的Provider.config中已经有很多不同数据库的数据驱动,而在 SqlMapp.config 的 database 配置的 provider 属性就是使用 Provider.co nfig中已有的不同驱动中的一个。以下是添加一个A 2.0数据访问驱动:OK,以上就是SqlMap.config和Provider.config的基本内容。下面我来介绍一下如果利用Iog4net来记录iBatisnet的一些运行日志记录。这也是我当初花了很多的时间才解决的一个 问题,因为记录这些日志太重要了,它可以记录下每次生成并执行的SQL语句,对我们排 除配置错误有非常重大的意义。而如果你是使用最新版的(当前是1.3.0),但是文档使用 的是1.2.1的话,那可能你怎么折腾都无法搞出结果来。按照121的文档介绍那样在web.co nfig(app.c on fig)加上合适的配置节后,然后把lo g4net.dll 和 IBatisNet.Common.Logging.Log4Net.dll 拷到 bin 目录下后,你可能会认为跟文 档介绍的一样,生成一个log.txt,并记录下日志。但事实不是这样的,在1.3.0的版本中还 需要再加上一个配置节组:vsectionGroup name=iBATIS配置组的配置值如下:!-logFactoryAdapter type = IBatisNet.Common丄ogging.Impl.ConsoleOutLoggerFA, IBatisNet.Common- vlogFactoryAdapter type = IBatisNet.Common.Logging.Impl.Log4NetLoggerFA, IBatisNet.Common.Logging.Log4Net经过以上的配置后,再运行程序,就会创建log.txt并且记录日志了。注意:即使是按以上 的配置后,有可能还是无法记录日志,那就可能是log4net.dll和IBatisNet.Common.Loggi ng.Log4Net.dll的中的一个或两个没有拷到bin目录,正常情况下,我们不需引用这两个程 序集,只需把它们拷到运行目录下,即使你需要记录日志,但找不到他们,程序仍然能正常 执行而不会抛出异常,如果你没有经验的话,解决这个问题可能需要你很多的时间。以上就是今天要介绍的内容了, Hope this helps。附注:1 参考资料: Data Mapper Guide-1.2.1.chm ;DataMapper-1.2.1.chm2 配置文件智能提示:把 provider.xsd SqlMap.xsd SqlMapConfig.xsd 三个文件拷 贝到VS 2005 : C:Program FilesMicrosoft Visual Studio 8XmlSchemas (安装目录)VS 2003 : C:Program FilesMicrosoft Visual Studio .NET 2003Common7Packa gesschemasxml (安装目录)下,就可以在VS IDE下编写配置文件时得到Intellis ense的帮助,前提是配置的文件的第一个节点写正确的命名空间和XSD文件。iBatis.Net 系列(3) 映射文件基础iBatis的核心就在于映射文件(Data Map XML File)。在映射文件里可以定义包括要执行各 种 SQL 语句,存储过程,输入参数映射,返回结果映射,缓存机制,并且能通过几种相对 比较复杂的配置实现对象之间的关联关系和延迟加载。这也是iBatis区别ORM框架的,具 备更灵活性,更高性能的关键所在。配置文件可以写得很简单,也可以很复杂。复杂配置文件也是出于更好的设计,更好性 能,更好扩展性方面的目的。再复杂的配置文件也是有限的,一个映射文件包括:MappedStatements、Parameter Maps、Result Maps、Cache Models 几个主要的配置,还包括 命名空间的配置,类型别名(前一篇中有介绍)的配置。1. Mapped Statements :顾名思义就是映射的语句声明。它是整个iBatis配置核心 的核心,真正将被执行的SQL语句(或存储过程)都是必须在这里被显式声明。在Mappe d Statements 里可以包含有:statement、select、insert、update、delete、procedure 这 6 种不同的语句类型。从词面理解相信就可以了解到这些类型功能的一大半了。 statement 可以包含所有类型的SQL语句(存储过程),它是一个泛泛的语句配置,没特别明确的职 责,相反,其它5种类型的语句配置就是专门负责各种不同的SQL语句。下面这张图列出 了各种类型的语句的不同职责和调用方法。Statement 类型属性子元素idpaimnetciCliiiisrultCliuiiipaiaincLcrMap rcsullMap tachcModcl方法inscrrlupdatedelete所有的査询方也xmlRs LiltNmncidIxirniiictcrCJaas paiainctcrMap Id paininclcrtlJaas paininctcrNIap所有的动态兀素所有的动态兀素idpniTiiiictcrf.Inss pairunctrNiapidpaiainetciSELECT EmployeelD丄astName,FirstName FROM Employees WHERE EmployeeID = #EmployeeID# OR LastName = #LastName#使用的是内联参数映射的方式,语句的在执行查询时只需为它提供Employee类型的对 象,它就会自动去读自己需要的 EmployeeID, LastName 属性的值,返回查询结果。在执 行时它所执行的语句如下:SELECT EmployeeID丄astName,FirstName FROM Employees WHERE EmployeeID =paramO OR LastName = param1所需的参数的提供方式如下:param0=EmployeeID,12, param1 = LastName,8bbb7bfb-c并且,在iBatis中还会指出各个参数的类型:paramO=Int32, System.Int32, param1 = String, System.StringSELECT EmployeelD丄astName,FirstName FROM Employees WHERE EmployeeID = #EmployeeID# OR LastName = #LastName# OR Country = #Countr、mpl#对于下面这个配置:1 234下一页它所使用的 ParameterMap 配置如下:在每一个Parameter映射元素可以指定每个属性对应的列,它的类型和对应的数据库 的类型,还可以指定当它为空值时的默认值,具体可以参看官方文档。但是可以看到,我们 期待它能和内联参数一样的使用方法,如上配置的那样。可是行不行呢?从程序的执行结果 来看,是不可以的。由于之前在配置SQL语句的时候基本都是使用内联参数没有特别注意 到这点。在使用Parameter Map的时候是不能用#property#的形式显示地指定要使用的属 性参数,只能通过“? ”顺序替代每一个parameter元素,如下:vselect id = Employees_SelectWithParameterMap2 parameterMap=Employee_SelectParameterMap resultClass=Employee listClass=ArrayListSELECT EmployeelD丄astName,FirstName FROM Employees WHERE EmployeeID = ? OR LastName = ? OR Country = ?可以看到,由于没有明显地指出EmployeeID对应哪个属性,那如果把上面的parameter 元素调换一下,那么EmployeeID所对应的参数值就发生变化了。同时,也是这个原因,通 过这种方式的参数映射,就无法重复利用每个参数了。如果仔细观察会发现,既然都指定了 column属性了,那它为什么不会自动去配置呢?其实在这边column属性是不起作用的, 它只会作用在执行存储过程的时候。也就是说上面的Parameter元素中的column属性不是 必须的。下面是一个存储过程的例子:Inse rtEmployeeInsertEmployee接受两个参数LastName和FirstName。我给它提供的映射参数如下:面这样的配置的结果是(其中逗号后面的是值):LastName = LastName,9a8bcO59-3, FirstName = FirstName,46887db0-2但是当我把他们的位置调换了一下。它的结果如下:LastName = FirstName,9a8bcO59-3, FirstName=LastName,46887db0-2也就是对储存过程也是一样的,参数映射关系仍然与parameter元素的顺序息息相关 的。Column属性仍然没有显示出它的作用。所以使用ParameterMap还有是有一定的局限 性的。但是对存储过程来说,就必须使用这样的方式,因为它只支持ParameterMap为它 提供参数,而不支持内联参数。最后总结列出几点ParameterMap需要特别注意的几个细节:1.在配置ParameterMap的时候,如果传入的参数对像是元数据类型(int,string etc), 那么在配置Parameter元素的时候,property的属性名使用value。通过这种情况主要使用 在为存储指定参数的情况下。2如果 ParameterMap 中配置的 parameter 元素不包含在传入参数对象中(属性或 IDicti on ar y对象的一个key,value项),将会产生异常,而不管在stateme nt中有没有用到。3. 在使用parameterMap的extends属性时,它将会继承extends值对应的paramet erMap配置,并且会继承它的所有的参数映射,并且顺序是从继承的那配置为基准开始计 算。这个在需要用到 extends 属性的时候要特别注意。4. 在为存储过程传参过程要特别注意,参数映射与存储过程的参数之间的顺序对应要正 确。而且必须为提供与存储过程足够的参数(parameter配置足够多),即使存储过程的部分 参数已经有默认值了。否则将抛出 System.ArgumentOutOfRangeException 异常。5正常情况下,应该尽量使用内联参数。iBatis.Net 系列(6) ResultMap我们将来讨论一下在iBatis中非常重要的一个内容,在我个人看来,能否真正用好iBatis的 一个关键,这就是ResultMap。字面上理解,它就是结果集的映射,就是将返回的记录逐个 字段的映射赋值给对象的属性上。其实如果没有特殊需求的话我们完全可以使用ResultCla ss来代替它,因为如果字段与属性一模一样的话,查询出来数据集会自动匹配到ResultCl ass 指定的类的实例对象,如果字段名不在属性中的话,那这个字段将不会被返回的实例体 类对象接受,相当于没有查询出这个字段一样的。每个ResultMap都有一个自己的ID,如果你在sqlmap.config中没有配置使用命名空间的话,那么这个ResulteMap ID是全局(这点在所有的iBatis配置元素都是一样的),R esultMap 一个重要的属性的是class,它将决定这个ResultMap对应的实例的类,换句话讲, 它的作用是指出结果集要映射的数据类型。在extends属性中可以设置它将要继承的Resu ltMap,如果给他指定的了值,那么它将会从super Resultmap继承所的映射配置字段。定 义如下:/esultMap如果你有正确配置了 iBatis的XSD架构文件的话,那么这时候就会提示resultMap的 定义是不完全的。没错,接下来就是要定义Result元素。每一个result元素都是定义一个 字段与数据类属性对应的映射。在每一个result元素有比较多的属性参数,其中property 和column是必须的,其它的参数属性都是可选的。所以我们在每一个resultMap中必须定 义超过一个以上的result定义。通常以下的配置就可以完成基本的配置了。但如果你需要更多的要求的话,result map仍然能够最大限度的满足你。columnlndex 属性提供了我们将数据集的第几个下标字段映射到指定的数据对象属性的方案,但是这种 方式应该尽量的少用,你会发现这对我们以后的维护和可读性会产生很大的副作用dbTyp e属性明确指出这个字段对应的数据库的类型,大多数情况我很少会用到。type属性则明确 指出这个字段将对应的数据对象属性的数据类型,通常如果你想保证类型安全的话,设置这 个属性是很必要的。resultMapping属性则稍微复杂一些,它是用在一种场景下,如果一个 数据类的属性本身不是基元数据类型,而是一个复杂数据类型的话,那我们就不可能很简单 地给它一个简单的result元素就了事了,还必须给他一个完整的resultMap。而resultMapp ing属性就是为了完成这个功能而存在的。它的属性值是一个已存在的resultMap的ID。n ullValue属性就没什么好讲的了,它是给出当这个字段的值为null的时候,它的默认值是多 少。select属性同resultMapping样比较复杂一样,先说一下它的属性值必须是一个返回 数据集合的查询语句的ID,能配置这个属性的数据类属性可以是一个基元类型,复合类型, 也可以是一个包括多条数据的集合类型,这些类型都行,没有问题的。它的一处重要的存在 意义就在于描述不同表之间的关系问题,通过本次的查询,你想不通过join的手段从另一 个表查询相关字段的时候,你就可以使用select属性。如下:statementsSELECT * FROM Children WHERE ParentID = #id#/statements这样就可以做到不用通过编程的方式来表示不同表的关联关系和数据读取问题。但是这 样有可能存在一种问题,如果你每次都要读取数据的时候,你会发现你会产生更多次的与数 据库交互的情况,并且即使你不是每次都需要这数据,那会不会造成数据读取的浪费呢?接 下来的 lazyLoad 属性就为我们提供了第二种问题的解决方案了,那就是数据的延迟加载, 没错,延迟加载可以大大改善数据访问的性能,它只是要需的时候才去读取这些数据,对于 主从表关系的时候,这样的方式可能是最好的解决方式了。OK,关于ResultMap的介绍就先到此为止,接下来我要记录一下,我在使用过程中 遇到的一些问题:一.在使用ResultMap的时候,你要特别注意,如果你在ResultMap中给出的配置 字段,但是你返回的数据集的时候却没有返回这个字段,那程序将出抛出异常。但是相反的, 如果你返回了一些字段,却没有在ResultMap给出配置定义的话,那么那些字段将不会被 处理而不会给你任何的提示,相当没有查询出这些字段。你要特别注意这个问题。二.如果没有特别需求的情况,我建议还是把数据类的属性设计成与数据库字段字一样的比 较,这样如果一般情况下我们都可以不用写这个ResultMap,事实上如果没有这样的特殊要 求,那么去写这个ResultMap仍然是一件非常耗时,并且容易出错的一份差事。三.在使用lazyLoad的时候要特别注意,不是什么类型的数据都可以lazyLoad的, 只有是实现的IList的接口的类型,并且数据类的属性定义为IList类型的字段才能被lazyLo ad。(关于是否只有IList类型的属性才能被lazyLoad的问题还需要探讨一下,因为就我使 用的经验只有这种类型才可以,甚至是Generic版的IList都不支持)。而且你在使用它的 时候,还不能把这个IList类型的属性转换成你真正的数据类型。因为在运行时,这个属性 会被包装成一个动态的类型,这个动态类型仍然实现了 IList接口,就是因为这个动态类型 才扩展了我们可以lazyLoad的功能。这时候在程序中使用的是运行时的动态类型所以你没 办法进行强类型转换。问题暂时没有想到更多了,如果以后还有关于resultMap的问题,我都会更新上来, 也希望大家一起来指正我的一些错误和不足,一起完善。不要让我的一些错误的实践误导了 初学者,谢谢。
展开阅读全文
相关资源
相关搜索

最新文档


当前位置:首页 > 办公文档 > 解决方案


copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!