科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道基于iBatis的通用持久层对象(1)

基于iBatis的通用持久层对象(1)

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

相对Hibernate等“全自动”ORM机制而言,iBatis以SQL开发的工作量和数据库移植性上的让步,为系统设计提供了更大的自由空间。研究过iBaits以后,发现有些通用的方法可以解决企业级应用的常规工作,就是设计一个通用的持久层对象。

作者:fellow99 来源:MATRIX 2007年12月10日

关键字:

  • 评论
  • 分享微博
  • 分享邮件

在本页阅读全文(共3页)

要注意的地方如下:

a、跟一般的iBatis配置文件不一样,该配置中没有包含resultMap,使用的就是resultClass的方式(效率没那么高的那种)。当然,也可以使用resultMap,这样就要为每个表写自己的配置文件了。因此,在该设计没完成前,我暂时先使用resultClass的方式。
b、上面只列举了最简单的增删改以及按id查询,并没有更复杂的查询,为什么呢?因为我还在研究中。。。研究通用的模板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 CustomPO 该对象在传入前应该先设置moduleTable和id参数,
* 并且使用setFieldList()函数设置字段列表(该设置决定所返回的字段)。
*/
CustomPO findByID(CustomPO po) throws Exception;
/**
* 通过传入moduleTable和parentID取得一条记录
*/
CustomPO findByParentID(String moduleTable, int parentID) throws Exception;
/**
* 通过传入CustomPO对象插入一条记录
* @param po CustomPO 该对象在传入前应该先设置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 moduleTable, 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 (returnId != 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;
else
fill(result, po);
 
c、增删改,没有返回值,值得一提的是增加操作完成后,po里面的id会更新,具体看前面相关的statement。

 //增删改
this.insert("customPO_insert", po);
this.update("customPO_update", po);
this.delete("customPO_delete", po);
 
5、前面是通用的部分,光是通用是不够的。因此我另外建立了一套配置文件,记录字段对应关系。看看我所定义的一个配置文件,挺简单的:

 <struct name="userInfo" table-name="tblUserInfo">
<field name="昵称" column="NICK_NAME" type="string" not-null="true" unique="false" />
<field name="姓名" column="FULL_NAME" type="string" not-null="true" unique="false" />
<field name="性别" column="SEX" type="string" not-null="false" unique="false" />
</struct>
 
其中,name是字段名,column是字段对应数据表的字段名,type是字段类型,not-null是是否不能为空,unique是是否唯一。只有name这个属性是必填的,column如果不填默认与name相等,type默认为string,not-null和unique默认为false。

配置文件的读取类在这里就省略了。

为什么要自己定义一套这个框架?好像挺多此一举的,但是没办法,iBatis配置文件的信息是封闭的,我无法取得。另外我考虑的是:

a、viewer层
在web开发中,我可以在这套配置框架的基础上,建立自己的标签,实现数据自动绑定的功能;GUI开发中也可以做相应的功能。
b、module层
可以做通用的业务操作,不需要为每个业务都都做独立的业务逻辑。

四、有什么优点、缺陷

1、优点

a、“通用”,一切都是为了通用,为了减少重复劳动,一个个项目面对不同的业务,其实说到底都是那些操作。各种持久成框架已经带给我们不少的方便,但是在实际业务逻辑的处理上好像还没有一个这样的框架。
b、极大地减少代码量。前面说了,数据库改一个字段,PO、DAO、module、JO、viewer、validator全都要改一遍。使用了这套东西,可以把绝大部分的劳动都放在配置文件和UI上。当然,这是完美的设想,对于很多情况,业务逻辑还是要手工写的。
c、好像没有c了。

2、缺点

a、通常通用的东西都缺乏灵活性,在我的实际应用中也发现了这样那样的问题,解决方法都是以通用为基本原则。但是如果针对的是某个项目,那就可以针对业务来修改了。
b、性能问题。因为使用resultClass,按照文档所说的,性能没有resultMap好。当然也可以使用resultMap,如前所说,就要对每个PO写配置文件了,工作量也不少。
c、也好像没有c了。

五、后话

我总是喜欢写一些通用的东西,总是想把它设计成万能的。但是经过多次失败总结出来,我发现通用的东西在很多情况下都等于不能用。但我就是喜欢往通用方面想,这个毛病不知道什么时候才能改得了。其实在Delphi平台中,我早就实现了相关的东西,但是用delphi总是限制于ADO+Data Module这样掉牙的模式。现在转向java,发现有iBatis、hibernate这么多好的持久层框架,自然有移植必要了。

查看本文来源

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章