用PVO简化JDBC数据库编程

来源:互联网 发布:营销软件三金网络 编辑:程序博客网 时间:2024/05/01 00:03
 
用PVO简化JDBC数据库编程
 
“如何同时提高一个软件系统的可维护性和可复用性是面向对象的设计要解决的核心问题。”
——摘自《Java与模式》
 
HashMap关系数据映射技术软件PVO是为了简化JBDC编程的复杂性、提高JDBC数据库编程效率,而开发的一个通用的抽象级JDBC程序设计工具包。与其说它是一个映射工具,更不如说它是一个简化JDBC编程的通用的API,它是一个“一次写成,到处运行的”抽象级数据库应用程序。它与现有的O/R工具有着本质的区别,一旦在PVO中建立了与数据库的连接,PVO将动态提取相关数据库信息,来完成几乎与数据库相关的全部基本操作,而不需要任何XML之类的数据库表的描述文件。正因为如此,尽管,目前它不够强大,然而,它的实用性、灵活性,却远比O/R工具好的多。
 
暂且看以下一个实例:
这个例子,共58行代码。至少实现了以下5项任务:
1.         新建并保存一条记录;
2.         查询记录数,并保存和显示;
3.         查询最新1000条记录,若不足,则取全部记录;
4.         分页显示1000条记录,每页设置50条记录;
5.         判断是否初始化了相关数据,若已经初始化,则不再运行相关代码。
 
通常应当将Java代码同Jsp分离,这里为了便于说明问题,将相关代码放在Jsp中。
 
[HashMap关系数据映射技术软件PVO应用范例:登记来访信息]
 
以下是范例中使用的数据库的表
 
create table visitinfo(
visitinfo_id bigint primary key,
sessionid varchar(64),
ip varchar(32),
begintime varchar(22)
)
 
以下是完整的init.jsp文件,如果想看效果,请点击http://www.aisun.cn主页中的链接登记来访信息
 
<%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %>
<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>
<%@ taglib uri="/WEB-INF/pvotag.tld" prefix="pvo" %>
<%@ page contentType="text/html; charset=GBK" %>
<%@ page import="java.util.*,java.sql.SQLException,cn.hkm.sql.*,cn.hkm.web.*" %>
<jsp:useBean id="form" scope="session" class="cn.hkm.web.BaseMapForm"/>
<html>
<head>
 <title>HashMap关系数据映射技术范例:登记来访信息</title>
 <%
 String isInit=(String)session.getAttribute("isInit");
 if(isInit==null){//用于判断是否已经初始化
    ProcessVO pvo=new ProcessVO(mypvo.web._Con.getCon());
    try {
      pvo.setAutoCommit(false);
      Map m=new HashMap();
      m.put("sessionid",session.getId());
      m.put("ip",request.getRemoteAddr());
      m.put("begintime",""+form.whatDateTime(session.getCreationTime()));
      Long ID=pvo.insertKey("visitinfo","visitinfo_id");
      pvo.updateARecord("visitinfo",m,"where visitinfo_id="+ID);
      int i=pvo.getRecordCount("visitinfo");
      session.setAttribute("as_VISIT_COUNT",""+i);//保存访问次数,供显示
      int j=(i-1000)<0?1:(i-1000);
      List v=pvo.getSomeRecord("select * from visitinfo",j,1000,false);//获取最新一千条记录,若不足则取全部记录
      pvo.commit();
      session.setAttribute("visitinfo_v",v);
      session.setAttribute("isInit","yes");
    }
    catch (SQLException ex){
      pvo.rollback();
      ex.printStackTrace();
    }
    finally {
      pvo.closeCon();
    }
 }
%>
</head>
<body bgcolor="#ffffff">
 <h3>范例:客户来访信息[总访问次数:<bean:write name="as_VISIT_COUNT"/>]</h3>
 <pvo:page id="list_v" name="visitinfo_v" length="50"/>
 <table cellpadding="0" cellspacing="1" width="100%" bgcolor="6699aa">
    <tr bgcolor="a0ffff" align="center">
      <td>来访时间</td>
      <td>会话ID</td>
      <td>来访IP</td>
    </tr>
    <logic:iterate id="record" name="list_v">
    <tr bgcolor="ffffff">
      <td><bean:write name="record" property="begintime"/></td>
      <td><bean:write name="record" property="sessionid"/></td>
      <td><bean:write name="record" property="ip"/></td>
    </tr>
    </logic:iterate>
 </table>
</body>
</html>
 
 
值得注意的是,使用PVO非常简单,不需要定义数据库表的XML描述文件,也不需要定义JavaBean或接口。用O/M工具完成以上几项任务,并不轻松。
 
什么时候选择PVO?
《J2EE设计开发编程指南》一书作者在第7章中做了这样一个结论:“不要假设O/R映射是所有数据存取问题的最佳解决方案。它在某些情况中工作的很好,但有时没有一点好处。”有兴趣的读者不妨找到该书读一读。程序总是在限定条件下产生的,如果不具体问题具体分析,一味使用一个工具,不是明智之举。使用O/R工具如此,使用PVO也是如此。以下是我个人对此类问题的一点看法:
1.         如果某段代码对运行性能要求特别高,则使用标准JDBC;并利用好数据库服务器本身的性能优势。
2.         如果对运行速度要求不是很高,O/R工具、PVO都是可选项。
3.         如果可以用异步方式使用结果集,PVO应当是一个不错的选择。
4.         如果看好软件的整体开发效率、整体质量,PVO应当是一个不错的选择。
5.         如果一个数据库表的字段越多,PVO带来的效率就越明显。反之,使用PVO,不见得有明显效果。
 
何以见得?我们不妨阅读一些“面向对象设计”方面的书籍,且看《Java与模式》第三部分 “面向对象的设计原则”,这里重点引用第3章的相关论述。
 
一个典型的软件生命周期大致如此:刚完成的系统如同一个美少女,在客户的要求下,修改后,脸上开始长“青春痘”,几经修改后“痘痘”越来越多,后来成为“legacy”系统,最终成为不得不抛弃的“腐烂”的系统。设计师可能会为其辩解,而真正的原因是什么呢?真正的原因有四个:过于僵硬、过于脆弱、复用率低、黏度过高。过于僵硬是很难在一个系统里加入一个新的性能,哪怕是很小的都很难。如果用这种观点来考察O/R工具,你会有什么想法呢?如果对一个字段进行了修改,不仅要改相应的业务处理代码,还要修改XML文件,可能还要修改一个JavaBean,甚至一个Java接口。过于脆弱是与软件过于僵硬同时存在的,是软件系统在修改原有代码时过于脆弱。对一个地方的修改,往往会导致看上去没有什么关系的另一个地方发生故障。…
XML作为通用的信息交换媒介,成为Web服务器、EJB服务器、数据库配置文件已经司空见惯,这样的应用确实需要,而且数量是有限的。然而,用XML文件来描述关系数据库表的信息,在Java中,并不是必须的,因为一旦在数据库中定义了表后,这些相关信息完全可以通过JDBC来获取。更可怕的,在客观现实中,就整个行业来说,对数据库表的需求数量是无限的,如果都要用XML文件去描述会导致同样无限数量的XML文件。不仅如此,使用O/M工具,可能还要定义无数的JavaBean、无数的Java接口。如此无限重复定义基础信息,又怎样谈软件开发效率呢?使用O/R工具不仅不能有效地提高系统的可维护性,也不能带来软件性能的提高,而且还不可避免的造成巨大的信息重复定义,它能带来的好处是十分有限的。这种不计成本的代码堆积,不仅带来的是软件难以维护,其所造成的时间、金钱的浪费可能是无法估量的,最终的结果,恐怕连软件的质量无法保证。O/R技术本身的复杂性,往往超过标准的JDBC,真正能掌握好O/R技术,恐怕需要相当长时间的努力。这些都是《J2EE设计开发编程指南》作者指出O/R利弊的原因吧。
 
关于面向设计的目标,《Java与模式》中指出:“一个好的系统设计应该有如下性质:可扩展性、灵活性、可插入性。这三条性质就是一个系统设计应当达到的目标。”如果用这三个目标来考察“HashMap关系数据映射技术软件PVO”,有理由相信,PVO是一个好的系统。
 
PVO工具软件,核心包与扩展包功能划分合理,核心包完全基于标准的JDK实现,实现了抽象级的与数据库的基本操作相关的几乎全部的方法;扩展包则针对基于Struts的应用开发提供了更简便的实现。同样,可以方便地基于核心包,扩展对其它应用的支持。对于PVO生成的结果,可以方便地生成XML文件;在JSP中,还可以很方便地生成JavaScript变量。PVO动态提取数据库操作相关信息,使得它能够“一次写成,到处运行”,其灵活性是无庸置疑的。PVO使用Map对象作为输入输出中数据的载体,充分利用了其“即插即用”的特性。
 
新修订的PVO_v1.2,着重依照《Effective Java Programming Language Guide》中一些基本原则进行。
1、核心包cn.hkm.sql完全依赖标准的JDK实现,因此为PVO今后的发展奠定了坚实的基础。取消了直接支持上传文件保存到数据库的作法,这部分功能移植到了扩展包BaseMapForm类中;删除了ProcessVO类中少量的不常用的方法;用List接口来引用Vector等具体的对象;增强了对数据库连接资源和事务的处理;用终结守卫者模式替代终结方法(注:这是容易引起争议的问题,在此不多加说明)。新增了对单表模拟树型结构的支持。
2、扩展包cn.hkm.web增强了BaseMapForm对表单数据的处理。特别是增强了对上传文件的处理。使得基于Struts的应用更加轻松。
 
PVO中一些基本的约定
1、用接口引用对象
2、若无结果集,则返回零长度List对象
3、若无记录,则返回零长度Map对象
4、零长度字符串存入数据库中将保存为null
5、返回值与标准Java库方法返回值一致
6、若仅仅是调用标准库中的方法,则方法签名与被调用方法签名一致
7、遵守驼峰式命名规则
 
由于个人学识能力有限,不当之处难免。所引起的话题,可能会有人反对,有人赞同。但最终目的只有一个:共同提高。
 
PVO刚刚起步,它需要不断完善,需要Java专家、程序员提出宝贵的意见,使它变得更好。
 
 
附:有关观点可参考以下著作
《Effective Java Programming Language Guide》(中文版) ([美]Joshua Bloch 著 机械工业出版社)
《Java与模式》第二部分 面向对象的设计原则(阎宏 编著 电子工业出版社)
《J2EE设计开发编程指南》([美]Rod Johson 著  电子工业出版社)
原创粉丝点击