ImageVerifierCode 换一换
格式:DOCX , 页数:8 ,大小:20.86KB ,
资源ID:12661514      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/12661514.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(基于iBatis的通用持久层对象.docx)为本站会员(b****3)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

基于iBatis的通用持久层对象.docx

1、基于iBatis的通用持久层对象ibatis介绍使用ibatis 提供的ORM机制,对业务逻辑实现人员而言,面对的是纯粹的Java对象, 这一层与通过Hibernate 实现ORM 而言基本一致,而对于具体的数据操作,Hibernate 会自动生成SQL 语句,而ibatis 则要求开发者编写具体的SQL 语句。相对Hibernate等 “全自动”ORM机制而言,ibatis 以SQL开发的工作量和数据库移植性上的让步,为系统 设计提供了更大的自由空间。作为“全自动”ORM 实现的一种有益补充,ibatis 的出现显 得别具意义。版权声明:任何获得Matrix授权的网站,转载时请务必保留以下作

2、者信息和链接作者:fellowArrayArray原文:关键字:iBatis;ORM一、为什么要设计“通用”的东西在大多数时候,我们所需要的持久层对象(PO)大多都是一张表(or视图)对应一个类。按照Hibernate的思想,就是抛开数据库的束缚,把焦点集中到业务对象中。而很多自动化工具的确让做到了通过表结构生成对应的对象,or通过对象自动生成表。对于小项目来说,一切都是简单的;对于有规范设计的项目来说,PO的设计也不是一件困难的工作。但是对于那些业务变动频繁的项目来说,改动PO可能成了一件很繁重的工作。试想一下,假设某个表需要增加一个字段:对于Hibernate(or iBaits),首先要

3、改配置文件,然后PO,然后DAO(也许没有),然后业务逻辑,然后JO,然后界面,etc,贯通了全部层次。恩,写程序的都不喜欢这些重复劳动,但是做企业级应用的谁不是每天在这些工作中打滚。研究过iBaits以后,发现有些通用的方法可以解决,就是设计一个通用的持久层对象。二、基于什么技术iBatis可以使用Map对象作为PO,Hibernate好像也有相关的功能(我没有细看,不确定)。iBatis执行一条指令的过程大概是这样的:其中圈圈1、2、3描述了iBatis最重要的三个对象。圈圈1:statement简单来说就是存储sql语句的配置信息,一个最简单的statement:insert into

4、PRODUCT (PRD_ID, PRD_DESCRIPTION) values (1, “Shih Tzu”)其中id属性是这个statement的唯一标识,全局不能重复。以上当然是最简单的了,没有参数也不需要返回值,但实际情况下基本都需要传入参数,下面就是介绍参数。圈圈2:参数对象主要分两种类型:parameterMap、parameterClass和Inline Parameter。其中parameterMap是配置文件定义传入参数表,如下:insert into PRODUCT (PRD_ID, PRD_DESCRIPTION) values (?,?);而parameterClass

5、是传入参数对象(JavaBean),如下:insert into PRODUCT values (#id#, #description#, #price#)Inline Parameter则是强化版的parameterClass,如下: insert into PRODUCT (PRD_ID, PRD_DESCRIPTION)values (#id:NUMERIC:-ArrayArrayArrayArrayArrayArray#, #description:VARCHAR:NO_ENTRY#);其中第一种方法看着就复杂,实际是为了兼容老版本留下来的,所以parameterClass是我们最常用

6、的方法。官方文档对parameterClass介绍很详细,因为这是核心之一,具体请自己查阅。有3个特性说明一下:a. parameterClass对象可以传入一个Map对象(or Map子类)。本来如果是传入JavaBean,程序会通过get/set来分析取得参数;而Map是key-value结构的,那程序会直接通过key来分析取参数。b. 看以下语句:insert into PRODUCT values (#id#, #description#, #price#, #classify.id#)蓝色部分#classify.id#翻译过来实际是product.getClassify().getI

7、d(),classify是Product对象的一个子对象。c. 在模板sql语句中除了“#”以外,还有“$”,它们两代表的意思当然不同了:select * from PRODUCT order by $preferredOrder$“#”在生成sql语句的过程中,会变成“?”,同时在参数表中增加一个参数;“$”则会直接替换成参数对象对应的值,例如上面的preferredOrder的值可能是“price”,则生成的sql语句就是:select * from PRODUCT order by price。*需要特别说明的是传入参数这一部分将会是后面正题“通用持久层对象”的核心,怎么个通用法,怎么设

8、计模板sql语句,都是在这部分上。圈圈3:结果对象跟参数对象差不多,也有两种,resultMap和resultClass,如下:resultMap就是配置文件中预定义了要取得的字段:select * from PRODUCTresultClass则是通过分析返回的字段,来填充结果对象:SELECT PER_ID as id, PER_FIRST_NAME as firstNameFROM PERSON WHERE PER_ID = #value#跟参数对象相反,结果对象一般使用resultMap形式。引用官方的话:使用resultClass的自动映射存在一些限制,无法指定输出字段的数据类型(如

9、果需要的话),无法自动装入相关的数据(复杂属性),并且因为需要ResultSetMetaData的信息,会对性能有轻微的不利影响。但使用resultMap,这些限制都可以很容易解决。三、正题来了,怎么做“通用持久层对象”1. 表结构:每个表都必须包含两个字段:id和parentId,其他字段按照需求来定义,其他各种索引、约束、关系之类的也按需求定义。2. 通用的持久层对象,CustomPO:public class CustomPO protected String moduleTable;/该PO对应的表名(视图名)protected int id;/表的idprotected int pa

10、rentID;/父表的id(如果有的话)protected Map fieldMap;/字段Map,核心,用于存储字段及其值public String getModuleTable()public void setModuleTable(String moduleTable)public int getId()public void setId(int id)public int getParentID()public void setParentID(int parentID)public Map getFieldMap()public void setFieldMap(Map fieldM

11、ap)public void copyFieldMap(Map fieldMap)/取得字段名列表public List getFieldList()/设置字段名列表。如果fieldMap没有相应的字段,则增加,字段值为null;如果有则不增加。public void setFieldList(List fieldList)/返回字段的“字段名 - 字段值”列表,使用com.fellow.pub.util.KeyValuePair对象作为存储public List getFieldValueList()那些成员变量的get/set就没什么说的,主要说说getFieldValueList()这个

12、方法。该方法返回一个列表,列表元素是一个key-value结构,简单来说就是把字段map序列化。在构造模板sql语句时会体现它的用途。3. iBatis对象配置文件CustomPO.xml:SELECT id, parentID$fieldList$ FROM $moduleTable$ WHERE id = #id#INSERT INTO $moduleTable$ (parentID$fieldValueList.key$)VALUES (#parentID#fieldValueList.value#)SELECT last_insert_id()UPDATE $moduleTable$

13、SET$fieldValueList.key$ = #fieldValueList.value# WHERE id = #id#DELETE FROM $moduleTable$ WHERE id = #id#要注意的地方如下:a. 跟一般的ibatis配置文件不一样,该配置中没有包含resultMap,使用的就是resultClass的方式(效率没那么高的那种)。当然,也可以使用resultMap,这样就要为每个表写自己的配置文件了。因此,在该设计没完成前,我暂时先使用resultClass的方式。b. 上面只列举了最简单的增删改以及按id查询,并没有更复杂的查询,为什么呢?因为我还在研究中

14、。研究通用的模板sql的写法。4. CustomPO对应的DAO:我使用了ibaits提供的DAO框架,很好用,不单支持ibatis的框架,还支持Hibernate、JDBC等等,而且是与ibatis本身独立的,完全可以单独使用。以后就不用自己写DAO框架了。一下是该DAO接口:public interface ICustomDAO /* * 通过传入moduleTable和id取得一条记录 */CustomPO findByID(String moduleTable, int id) throws Exception;/* * 通过传入CustomPO对象取得一条记录 * param po

15、CustomPO 该对象在传入前应该先设置moduleTable和id参数, * 并且使用setFieldList()函数设置字段列表(该设置决定所返回的字段)。 */CustomPO findByID(CustomPO po) throws Exception;/* * 通过传入moduleTable和parentID取得一条记录 */CustomPO findByParentID(String moduleTable, int parentID) throws Exception;/* * 通过传入CustomPO对象插入一条记录 * param po CustomPO 该对象在传入前应该

16、先设置moduleTable和id参数, * 并且使用setFieldMap()函数设置“字段-值”对。 */void insert(CustomPO po) throws Exception;/* * 通过传入CustomPO对象更新一条记录 * param po CustomPO 该对象在传入前应该先设置moduleTable和id参数, * 并且使用setFieldMap()函数设置“字段-值”对。 */void update(CustomPO po) throws Exception;/* * 删除moduleTable和id所对应的记录 */void delete(String mo

17、duleTable, int id) throws Exception;我没有把所有的方法都列出来,反正挺简单的,跟一般的DAO没什么分别。另外列几个实现的片断:a. 统一的数据装填函数,需要手工把id和parentID字段去掉。protected void fill(Map result, CustomPO po) Long returnId = (Long) result.get(id);Long returnParentID = (Long) result.get(parentID);result.remove(id);result.remove(parentID);if (return

18、Id != null) po.setId(returnId.intValue();if (returnParentID != null) po.setParentID(returnParentID.intValue();po.setFieldMap(result);b. 一般的查询,返回的是一个map,然后再用fill()函数/查询 Map result = (Map)this.queryForObject(customPO_findByID, po);/处理返回结果if(result = null)po = null;elsefill(result, po);c. 增删改,没有返回值,值得一

19、提的是增加操作完成后,po里面的id会更新,具体看前面相关的statement。/增删改this.insert(customPO_insert, po);this.update(customPO_update, po);this.delete(customPO_delete, po);5. 前面是通用的部分,光是通用是不够的。因此我另外建立了一套配置文件,记录字段对应关系。看看我所定义的一个配置文件,挺简单的:。其中,name是字段名,column是字段对应数据表的字段名,type是字段类型,not-null是是否不能为空,unique是是否唯一。只有name这个属性是必填的,column如果

20、不填默认与name相等,type默认为string,not-null和unique默认为false。配置文件的读取类在这里就省略了。为什么要自己定义一套这个框架?好像挺多此一举的,但是没办法,ibatis配置文件的信息是封闭的,我无法取得。另外我考虑的是:a. viewer层:在web开发中,我可以在这套配置框架的基础上,建立自己的标签,实现数据自动绑定的功能;GUI开发中也可以做相应的功能。b. module层:可以做通用的业务操作,不需要为每个业务都都做独立的业务逻辑。四、有什么优点、缺陷1. 优点:a. “通用”,一切都是为了通用,为了减少重复劳动,一个个项目面对不同的业务,其实说到底都

21、是那些操作。各种持久成框架已经带给我们不少的方便,但是在实际业务逻辑的处理上好像还没有一个这样的框架。b. 极大地减少代码量。前面说了,数据库改一个字段,PO、DAO、module、JO、viewer、validator全都要改一遍。使用了这套东西,可以把绝大部分的劳动都放在配置文件和UI上。当然,这是完美的设想,对于很多情况,业务逻辑还是要手工写的。c. 好像没有c了。2. 缺点:a. 通常通用的东西都缺乏灵活性,在我的实际应用中也发现了这样那样的问题,解决方法都是以通用为基本原则。但是如果针对的是某个项目,那就可以针对业务来修改了。b. 性能问题。因为使用resultClass,按照文档所说的,性能没有resultMap好。当然也可以使用resultMap,如前所说,就要对每个PO写配置文件了,工作量也不少。c. 也好像没有c了。

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1