已阅读5页,还剩20页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
12.1 IBatis框架介绍 Hibernate框架的工作原理是,通过XML的映射文件将数据库中的表与简单Java对象对应起来,然后在运行时系统会自动为这些映射关系生成SQL,而程序员只要通过对象之间的操作,就可以完成对数据库表的操作。这样对象和表之间的映射关系就是一个O/R Mapping。IBatis框架则不同,它也有一个XML的映射文件,可是在这个映射文件中却不是通过简单Java对象与数据库表的字端进行关联,而是通过常见的SQL语句来描述。也就是说,将一个简单Java对象映射成了一句SQL语句。程序员在编码时同样只需对对象进行操作就可以同样完成对数据库表的操作。在表面看来,对象和表之间仍然存在映射关系。简单的说,就是Hibernate框架通过对象和表字端映射来生成SQL完成持久层的工作,而IBatis框架是通过对象和SQL之间映射来完成持久层的工作。IBatis的开发者曾经说过“你已经知道SQL,为什么还要学习其他东西”。的确如此,没有了EJB QL和HSQL,只有SQL,这对于从传统DAO转到持久层框架的程序员来说无疑是一个福音。12.2.1 IBatis框架的组成下面就来看一下IBatis到底为程序员带来了什么。1SQL MapsSQL Maps是整个IBatis框架的核心部分。类似Hibernate框架的对象关系映射文件一样,在这里需要提供一个XML文件来实现简单Java对象到SQL声明的映射。SQL Map并不单单是这么一个XML文件,它其实是一个框架。它的工作方式是:在执行映射声明时,SQL Map框架将创建一个JDBC的PreparedStatement实例(这在传统的JDBC DAO中非常常见),用描述在XML中的对象作为PreparedStatement实例的参数,执行PreparedStatement并从ResultSet中创建结果对象。读者可以认为这是从VO到PO再转化成VO的返回过程,而它是通过自定义的SQL来完成的。2IBatis DAO框架IBatis框架中提供了一套独有的DAO框架来封装持久层的操作。IBatis DAO框架要求程序员提供一个DAO接口,并以DAO实现类来实现它。通过一个XML让DAO接口知道哪个DAO实现类会实现它。这样的好处是,以DAO接口来处理事务管理,根据不同的业务需求选择DAO实现类来提供各自的实现。对于调用DAO接口的客户端来说,仅仅对DAO的配置XML进行修改,就可以完成工作而无需修改任何编码。3附带的工具类IBatis的jar包中附带了一系列非常有用的工具类。比如Resources为从classpath中加载资源,提供了易于使用的方法。SimpleDataSource类是JDBC2.0的DataSource接口的一个简单实现。ScriptRunner类用于执行SQL语句,例如创建数据库schema,或插入缺省数据以及测试数据等。12.2.2 IBatis框架的SQL Map配置文件 在IBatis 的SQL Map框架中,需要一个配置文件来声明一些基本信息。该文件类似Hibernate框架的配置文件“hibernate.cfg.xml”,SQL Map初始化期间,会自动在classpath中寻找这个文件,并读取其中的配置信息。 配置文件的名称并不重要,可以由程序员来指定,这里假设该配置文件名为sql_map_config.xml。在配置文件中通常会配置如下这些持久层框架信息:q 数据库连接JDBC。q SQL Map映射文件的加载。q SQL Map的配置和优化设定。下面看一个sql_map_config.xml示例12.1:例12.1:sql_map_config.xml 在这个配置文件中,明确表示了SQL Map框架的配置参数,以作为根结点是必不可少的。随后使用了元素、元素和元素。在元素中提供了多个属性来配置和优化SQL Map运行时的实例:q maxRequests属性指定了同时执行SQL语句最大运行数。q maxSessions属性指定了同一时间内活动的最大Session数。所谓Session就是一个请求或一个SQL Map运行时实例自动获得的会话。q maxTransactions属性指定了最大事务处理的线程数。q cacheModelsEnabled属性指定了SQL Map运行时实例的缓存Model是否开启。q lazyLoadingEnabled属性指定了持久化数据是否延迟加载。q enhancementEnabled属性指定了全局性的启用或禁用字节码增强,以优化访问POJO变量属性的功能。q useStatementNamespaces属性指定了在SQL Map映射文件中是否用全限定名来引用映射声明。元素用来配置事务管理。元素的属性type指定了所使用的事务管理器的类型。该属性值可以是一个别名,也可以是一个类名,本例中所使用的JDBC就是一个别名,它是由IBatis框架所提供。包含在IBatis框架中的事务管理器有三个:除了本例所使用的JDBC(用来管理事务)外,还提供了JTA和EXTERNAL两个事务管理器。其中JTA将提供全局的事务管理,EXTERNAL则可以让程序员自行管理事务。元素的子元素为JDBC数据源设置了一系列参数,这些参数将被用于连接数据库。在SQL Map架构中提供了三种JDBC连接的方式,可以利用type属性来设置这三种方式:q SimpleDataSourceFactory是IBatis框架提供的基本连接池的实现,当容器没有提供数据源时可以选择它。SimpleDataSourceFactory的别名已经由IBatis框架所定义,名为“SIMPLE”。本例就是使用SimpleDataSourceFactory作为连接池。q DbcpDataSourceFactory是IBatis框架使用DBCP连接池所提供的服务。在Web容器中经常会使用它,在第三章的完整示例中曾经使用它来配置Struts框架部分DAO的JDBC连接池。DbcpDataSourceFactory的别名已经由IBatis框架所定义,名为“DBCP”。q JndiDataSourceFactory是IBatis框架提供的对JNDI命名服务的支持,它可以在容器中利用JNDI从上下文中找到连接池的实现。在介绍EJB的配置以及Hibernate框架时,曾经将它作为在JBoss服务器中取得连接池的实现,在IBatis框架中是一样的道理。JndiDataSourceFactory的别名已经由IBatis框架所定义,名为“JNDI”。本例中最后一个元素是元素,利用属性resource来指定SQL Map映射文件的路径定义。SQL Map映射文件可以从classpath中得到,所以这个路径的定义是以classpath为根目录开始的。本例中没有定义其他路径,说明SQL Map映射文件将被直接放置在classpath路径下。SQL Map映射文件可以有多个。12.2.3 IBatis框架的SQL Map映射文件在IBatis框架中,利用一个映射文件来定义需要持久化的对象,在这个文件中SQL语句是最显眼的,这个映射文件的目的就是将SQL映射到对象。下面先看一下映射文件的主要功能:q 定义一个持久化的Java类。q 映射VO中的变量属性为表字段。q 根据SQL来持久化对象。q 可以定义随意使用的SQL。q 支持各种条件语句的定义。q 支持数据库自动主键的生成。q 支持存储过程。q 支持将结果映射成XML文档。q 支持多表关联。1. 一个具体映射文件的示例下面看一个具体映射文件的示例。在这之前,表结构和VO将沿用第十一章的例11.2 AttackSolution.java,从这里可以看出,IBatis框架的VO也是一个POJO。映射文件的文件名可以随意指定,只要在sql_map_config.xml中的元素定义中与之对应即可。与例12.1 sql_map_config.xml的元素对应的,将定义映射文件名为fw_attacksolution_SqlMap.xml,示例见12.2,在示例12.2中将分段解释各个应用:例12.2:fw_attacksolution_SqlMap.xml映射文件的根节点是。namespace是该的命名空间,因为SQL Map映射文件可以有多个,而对于SQL Map来说所有映射文件都是全局性的。这意味着在SQL Map中的标识只能是惟一的,利用namespace和标识的全限定名就可以进行区别,前提是,配置文件中的useStatementNamespaces属性必须设置为true。 元素是最常用的元素,使用元素可以定义数据返回的对象。其id属性在之后的各种带返回对象的元素中,将作为返回对象的标识。即,返回结果将会以calss属性定义的对象作为承体。本例中定义返回结果到VO对象Attacksolution。元素的子元素以column属性作为数据库表字段、并以property字段作为VO变量属性进行映射。返回结果根据字段设置VO变量属性的值。jdbcType属性则指定了数据库表中字段的数据库类型。 !- 元素可以划分出SQL语句的动态部分。动态部分可以包含任意多的条件元素。条件元素决定,是否在语句中包含其中的SQL代码。- !- 若存在该变量属性,则指定可以使用元素的实体内容。- attack_event_code is null attack_event_code is not null attack_event_code is not null attack_event_code = #attack_event_code# attack_event_code = #attack_event_code# 以本例中最后一个来说明:当某个对象存在变量属性OR_attack_event_code_EQUALS时,将定义“or attack_event_code = ?”的条件语句,并判断是否是第一个条件。如果是第一个条件则会以“where”来替换“or”,成为“where attack_event_code = ?”,而“?”将以某个对象中变量属性attack_event_code的值来替换。说明:在本例中,OR_attack_event_code_EQUALS并不是VO对象的变量属性,因此将会有一个新的Java类来提供该变量属性,这在之后的介绍中可以看到,这种做法是非常灵活的。 !- resultMap属性与元素的id属性匹配表示结果映射到的VO,当查询结果是多条记录时,会返回一个集合 - !- 元素的实体内容为SQL语句,其中由“#”包含的内容将根据parameterClass属性指定的对象中找到匹配的变量属性值。 - select attack_event_code, attack_mean, attack_action from fw_attacksolution where attack_event_code = #attack_event_code# 本例中,该元素的含义是:以带条件的预处理SQL查询表fw_attacksolution,条件的“?”参数将通过struts.sample.cap11.sample2.entity.Attacksolution类的attack_event_code变量属性得到,查询结果被返回到元素所指定的VO struts.sample.cap11.sample2.entity.Attacksolution中。 select attack_event_code, attack_mean, attack_actionfrom fw_attacksolution!- 子元素可以包含动态SQL到元素的实体内容中去- order by $ORDER_BY_CLAUSE$ 以上这部分仍然使用元素来定义一句查询SQL,不过这部分的SQL复杂一些,因为这是一句动态SQL。在本例中需要注意的是,SQL的传入参数被使用parameterClass属性指定的java.util.Map来传入,这个Map的内容必须符合Map实例put(method, value),在底层框架处理时会如同得到一个POJO的变量属性名、变量属性值一样来取得这个Map中的每一行作为参数名和参数值。本例的含义是:当传入参数中存在“ORDER_BY_CLAUSE”变量属性时,就将“ORDER_BY_CLAUSE”的值替换$ORDER_BY_CLAUSE$,形成一句完整的order by语句。说明:“$”和“#”同样都是替换变量属性的值,有什么区别呢?“$”是一般的替换,用变量属性值来替换“$”包含的内容。而“#”与“$”完全是处理方式的区别,包含在“#”中的变量属性值会被用来在带“?”的SQL中替换“?”,进行SQL预处理。 delete from fw_attacksolution where attack_event_code = #attack_event_code# 元素也是执行一句SQL,但是它执行的是删除功能的SQL。元素拥有id、parameterClass和parameterMap三种属性,但是没有resultClass和resultMap这两个返回性质的属性,所以元素执行后的SQL是无返回值的。 delete from fw_attacksolution 以上也是一个元素执行的删除语句,惟一不同的是它有了动态SQL的特性,所以元素支持所有的动态SQL。 insert into fw_attacksolution (attack_event_code, attack_mean, attack_action) values (#attack_event_code:VARCHAR#, #attack_mean:VARCHAR#, #attack_action:VARCHAR#) 元素执行的是新增记录的SQL语句,它的特性和元素类似。本例中的insert语句会为表fw_attacksolution插入一条记录,记录中的每个字段都是VARCHAR型,通过parameterClass属性指定的对象来传入变量属性值。 update fw_attacksolution set attack_mean = #attack_mean:VARCHAR#, attack_action = #attack_action:VARCHAR# where attack_event_code = #attack_event_code# 元素执行的是更新记录的SQL语句,它的特性和、元素一样,也必须显式地声明所更新的数据库表字段的类型,支持所有的动态SQL。2. 其他条件判断元素和属性IBatis框架对于动态SQL的支持不仅提供了元素,还提供了其他类似的元素,如下所示:q 元素:当不存在对象的变量属性时,可以使用元素的实体内容。q 元素:当对象的变量属性为null时可以使用元素的实体内容。q 元素:当对象的变量属性不为null时可以使用元素的实体内容。q 元素:检查对象的变量属性为空时可以使用元素的实体内容。q 元素:检查对象的变量属性不为空时可以使用元素的实体内容。以上这些元素都拥有prepend属性和property属性,property属性被作为某个对象的变量属性。prepend属性指定了条件元素,具体如下所示:q 元素:在比较对象与对象之间的变量属性,或对象与静态值相等的条件下,可以使用元素的实体内容。q 元素:在比较对象与对象之间的变量属性,或对象与静态值不相等的条件下,可以使用元素的实体内容。q 元素:比较对象与对象之间的变量属性,或对象与静态值是否存在前者大于后者的情况,若存在,可以使用元素的实体内容。q 元素:比较对象与对象之间的变量属性,或对象与静态值是否存在前者大于且等于后者的情况,若存在,可以使用元素的实体内容。q 元素:比较对象与对象之间的变量属性,或对象与静态值是否存在前者小于后者的情况,若存在,可以使用元素的实体内容。q 元素:比较对象与对象之间的变量属性,或对象与静态值是否存在前者小于且等于后者的情况,若存在,可以使用元素的实体内容以上这些元素都拥有:prepend、property、compareProperty、compareValue四个属性。prepend属性指定了条件元素;property指定了某个对象的变量属性;compareProperty作为另一个对象的变量属性与property指定的某个对象的变量属性进行比较;compareValue作为一个静态值与property指定的某个对象的变量属性进行比较。compareProperty和compareValue属性至少使用一个。3. 元素的其他属性元素中,除了本例所提供的属性外,还提供了resultClass、parameterMap两个可选属性。q resultClass属性明确指定了返回结果的全限定名对象。resultClass并不常用,因为它没有了映射数据库字段的持久化特性。q parameterMap属性则指定了传入参数的一个标识,读者可以想象到,同样会由元素来定义一个传入参数的对象,并用id来惟一标识它。的确如此,和的写法十分类似,但它不必要映射到表中字段,因为仅仅是作为一个传入参数的对象没有持久化的概念。元素并不常用,parameterMap属性也不常用,一般来说用parameterClass属性已经足够满足大多数的需要了。4其他SQL执行元素除了本例中所见到的执行SQL的元素外,IBatis框架还提供了其他的SQL执行元素。q 元素,通用的SQL执行元素,可以执行任何SQL语句。在上例中的所有SQL语句,都可以使用元素来替换。元素还提供了一个新的属性xmlResultName作为将返回结果生成一个XML文档。q 元素,用于执行存储过程。元素也提供了xmlResultName属性来返回结果生成XML文档。12.2.4 其他重要特性最后说明一下在例12.2中没有出现、但比较重要的特性。1利用元素来生成自动主键在IBatis框架中可以利用数据库原有的特性来生成自动主键。比如常见的用法:用sequence来生成主键的示例,这是一个预生成的主键。 SELECT STOCKIDSEQUENCE.NEXTVAL AS ID FROM DUAL insert into USER (USER_ID,USER_NAME) values (#id#,#userName#)另一常见的用法:利用identity来生成主键的示例,这是一个后生成的主键。 insert into USER (USER_NAME) values (#userName#) SELECT IDENTITY AS ID 2xmlResultName属性来返回XML文档在、元素和元素中,都可以使用xmlResultName属性来实现将结果集写到XML文档的功能。 SELECT USER_ID as id, USER_NAME as userName, USER_SEX as userSex, FROM USER WHERE USER_ID = #userId#执行完成后,会生成如下的XML文档。 1 RW M可以看到,resultClass属性被定义成了“xml”,这是必需的。xmlResultName属性所定义的值被用作XML文档的根元素,而select中所使用表的别名被用作了根元素的子元素。12.2.5 在VO中描述对象间的关系与介绍Hibernate框架映射关系时一样,这里将之前的表结构改成如下的两张。看一下新表attack_document_parents的表结构,表12.1:表12.1 attack_document_parents的表结构字段名说明KEYIndex类型长度parents_attack_event_code主攻击代号KIvarchar30pattack_mean主攻击说明varchar1000修改之前的fw_attacksolution表结构如表12.2:表12.2 fw_attacksolution的表结构字段名说明KEYIndex类型长度attack_event_code攻击代号KIvarchar30attack_mean用户名varchar1000attack_action攻击解决方案varchar1000parents_attack_event_code主攻击代号Fvarchar30这两张表的对应关系,从attack_document_parents表来看就是“一对多”的关系,而从fw_attacksolution表来看就是“多对一”的关系。fw_attacksolution表的parents_attack_event_code字段作为外键与attack_document_parents的parents_attack_event_code字段相关联。1. 映射attack_document_parents的VO在这里假设一个映射attack_document_parents表的VO名为PattackDocument.java。VO的变量属性就不多描述了,这里仅给出作为关系映射的变量属性那一段代码:/* 由于attack_document_parents与fw_attacksolution是一对多的关系* 所以在对象之间的关系中就使用List来表明这层关系*/private ArrayList attackSolution;public ArrayList getAttackSolution() return attackSolution;public void setAttackSolution(ArrayList attackSolution) this.attackSolution = attackSolution;这段代码表示映射attack_document_parents表与fw_attacksolution表之间为一对多关系的,是一个名为attackSolution的变量属性,声明为ArrayList类型。attackSolution变量属性表明了在PattackDocument VO中,对于AttackSolution VO,一个PattackDocument VO可以包含多个AttackSolutionVO。2. 映射fw_attacksolution的VO映射fw_attacksolution表的VO名为AttackSolution.java。VO的变量属性不作过多描述。这里给出作为关系映射的变量属性的一段代码:/* 由于fw_attacksolution与attack_document_parents是多对一的关系* 所以在对象之间的关系中* 每个实例AttackSolution都会对应一个PattackDocument*/private PattackDocument pattackDocument;public PattackDocument getPattackDocument() return pattackDocument;public void setPattackDocument(PattackDocument pattackDocument) this.pattackDocument = pattackDocument;这段代码表示映射fw_attacksolution表与attack_document_parents表之间为多对一关系的,是一个名为pattackDocument的变量属性,声明其为PattackDocument类型。pattackDocument变量属性表明了在AttackSolution VO中,对于PattackDocument VO,一个AttackSolution VO只能指定一个PattackDocument VO。12.2.6 利用映射文件描述对象间的关系 映射两表之间的关系通过两个和两个元素来完成,用VO来描述两表之间的关系在IBatis框架中,其实仍然是通过SQL来完成的。怎样用SQL来表达“一对多”和“多对一”的关系呢?可以利用主表的主键作为从表的外键对从表查询,得到的结果就是“一对多”的关系。那么“多对一”呢?可以利用从表的外键对主表进行查询,只能得到惟一的一条记录。因此,必须首先做两个SQL。1. 用SQL描述关系 select * from fw_attacksolution where parents_attack_event_code = #parents_attack_event_code# select * from attack_document_parents where parents_attack_event_code = #parents_attack_event_code#利用元素来完成两句SQL语句,id为“getAttackSolution”的一句,表示根据attack_document_parents表的主键到fw_attacksolution表中进行查询,得到的是多条fw_attacksolution表中的记录,这就是“一对多”的关系描述。id为“getPattackDocument”的一句代码,是根据parents_attack_event_code字段到attack_document_parents表中进行查询,由于parents_attack_event_code字段是attack_document_parents表的主键,所以查询结果必然只有一条,那这就可以表示“一对一”的关系。2. 关系的对应接着需要将这些SQL映射到对象上去。在PattackDocument VO中有一个变量属性的类型为List,名为attackSolution,它表示了多个AttackSolution VO的集合,那么这在SQL映射到对象的元素中怎么表示呢?请看下面的代码: 和没有关系对应的元素相比,多了一个select属性,这个select属性在关系映射中的作用非常大,通过select属性指定的标识可以惟一找到一句查询SQL,而这句查询SQL就表达了“一对多”的关系。这段代码的解释可以是这样的:如果有查询返回的是“get-pattackDocument-result”所指定的VO,当将结果集写入VO的变量属性时,得到一个JDBC无法识别的List类型。于是底层框架就会查找select属性所指定的查询S
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 电子商务数据分析与应用(AI+微课版)(第3版) 课件全套 邵贵平 任务1-9 数据分析认知 -竞争对手数据分析
- 高中生物教资面试生理结构专项真题演练试卷
- 湖南农业岗2026面试自测卷习题汇编含答案
- 农业岗2026事业编面试自测卷含答案
- 财务税务-金税四期下-53项全套预警指标汇 总表
- 2026年高中数学函数应用问题专项训练课件
- 第二单元 第4课《数据分包灵活传》课件(内嵌视频)2026-2027学年人教版初中信息科技七年级全一册
- 2026年云南省普洱市毕业升学考试模拟卷数学卷含解析
- 2026年《短视频直播运营》电商高职期末解析试卷
- 现代物流学理论知识考核试题及答案
- 中国羊水栓塞诊治指南2025版
- 二手天车销售合同
- 2026年人工智能训练师(二级)理论基础真题及解析
- 江南大学介绍
- 行书课件教学课件
- 2025年秋季学期国家开放大学《理工英语4》形考任务综合测试完整答案(不含听力部分)
- 2025年山东事业编考试真题(附答案)
- 2025国考北京证监会计专业科目高频考点及答案
- 河南省安全生产考试点合规性检查表
- 装配钳工试题题库及答案
- GB/T 45602-2025船舶与海洋技术可调式滚轮闸刀掣链器
评论
0/150
提交评论