无为

无为则可为,无为则至深!

  语源科技BlogJava :: 首页 :: 联系 :: 聚合  :: 管理
  190 Posts :: 291 Stories :: 258 Comments :: 0 Trackbacks
感谢伟大的 Java 技术、感谢天才之作《 Java Developers ALMANAC 》 , 它们成就了 PVO 技术的诞生。也许是我个人的偏见,到目前为止,真不知道还有什么技术会像 PVO 这样给数据库编程带来如此之高的效率,使用起来却是如此的简单!
我曾经拜读过 OMR 、 JDO 之类技术方面的文章,见到一大堆复杂的技术真让人望而却步;也听别人介绍过 hibernate 技术,在网上也见到过不少人在谈论 hibernate 技术,他们总是津津乐道,而给我的感觉总是一盆雾水。在探索和迷茫的过程中,不禁要问, Java 本来就是一个高效、强大的象征,为什么会被 OMR 、 JDO 、 hibernate 之类弄得如此复杂?在简化数据库编程方面,难道就没有更好的方法吗?我与其把大量的精力花在钻研 OMR 、 JDO 、 hiberlate 之类的技术上,还不如多花些精力钻研 Java 技术本身,从中去寻求解决之道。于是一个实用的 HashMap 关系数据映射技术历时半年,在本人开发“ 皖南热线网站 ”之前终于诞生了,并在“皖南热线网站”的开发过程中不断得到完善、充实、检验。
PVO , Process Value Object 的缩写,意为值对象加工, ProcessVO 是本案的核心类,故将此技术简称为 PVO 技术 。 在简化数据库编程方面,这是一项重要的技术创新 。无论是与常规的 JDBC 数据库编程技术相比,还是与现有流行的各种数据映射技术相比,此方案可能会在一个项目开发中,将数据库的编程效率提高数倍、甚至是数十倍,如果一个表的字段有数十个,就会存在这样的可能性。数据库字段越多, PVO 技术能带来的编程效率就越明显 。为什么 PVO 技术会有如此之高的编程效率?主要原因有以下几点:
1、Java 容器技术、 Java 实用类技术本身就是高效、成熟的技术。
2、 不论是读取数据,还是存入数据,均使用了 JDBC 元数据技术、反射技术来自动实现记录与 HashMap 之间的映射、结果集与 Vector 之间的映射。
3、 免去了复杂的 XML 或 Properties 之类的配置。
4、SQL 标准语句参数化生成技术,会将所映射的 HashMap 对象,自动转化成 SQL 标准语句的一部分,以供 JDBC API 调用;不再需要你去调用 rs.getString(fieldName) 、 pstmt.setString(i , objectValue); 之类的方法了。
5、 如果是进行 Web 应用开发,本方案提供的 BaseMapForm 重载了 Struts ActionForm 的 reset 方法,除了上传文件,只用一个 Map record 属性,来取代其它所有的属性,以不变应万变,再不需要你去定义一大堆属性了。
6、 如果一个字段类型发生了变化,甚至是添加了几个新字段,再不须要你去修改业务逻辑部分的代码了。
PVO 技术方案符合 DAO 设计模式思想,有效地实现了数据库访问操作与业务逻辑的分离。核心类 ProcessVO 封装了与数据库相关的所有基本操作,如:插入、更新、删除、查询,并且实现了对查询结果集进行分页、筛选、排序、备份、获取子集的多种算法。此案通用性强,在 EJB 、 Application 、 Servlet 、 Applet 等应用中均可不受限制地方便使用。 PVO 不但可以大大提高数据库编程的效率,同时可以大大减轻数据库服务器数据流量的负担。
支持标准的 SQL 操作,如:插入、更新、删除、查询(包括多表查询)。
运用 Java 反射技术来实现 HashMap 与关系型数据之间的映射。
运用 Java 反射技术,参数化生成 SQL 标准语句,供 JDBC API 调用。
针对每一条记录,使用 HashMap 对象作为数据的载体,这个 HashMap 对象的键名是表中的字段名,或是字段的别名,键值为字段值,键值的类型是字段所对应的 JDBC API 的 Java 类。 针对数据库的操作,如:插入、更新、删除、查询,该方法会将所传递的 Map 型参数转化成 SQL 语句的组成部分,自动生成完整的标准的 SQL 语句,供 JDBC API 调用。
支持复杂的多表查询,针对每一个查询结果集,用一个 Vector 对象存贮,而这个 Vector 中的每一个元素均是一个 HashMap 对象,这个对象映射了一条记录。
充分利用了成熟的丰富的 Java 容器技术,实现了对这个 Vector 查询结果集进行分页、筛选、排序、备份、获取子集的多种算法。
基本技术包括:
JDBC 、 JDBC 元数据技术;
Map 、 Vector 等容器技术;
Java 反射技术;
通用 SQL 标准语句参数化生成技术及其算法;
HashMap 与关系数据库记录之间的映射技术及其算法。
1、 包名:核心包 cn.hkm.sql 、 web 应用包 cn.hkm.web
2、 下载 PVO_v1.0
3、 类文件:
cn.hkm.sql 包括 : ProcessVO 、 DbCon 、 Tool 、 WhereString 、 QueryString
cn.hkm.web 包括: BaseMapForm 、 PvoPageTag 、 PvoSqlTag 、 PvoRecordTag 、 PvoImgsTag 、 PvoImgTag 、 PvoShowImgTag 、 PvoRecordMapTag 以及标志库描述文件 pvotag.tld
    
1、 查询,例:
ProcessVO pvo=new ProcessVO();
pvo.setCon(con);
// 也可用 ProcessVO pvo=new ProcessVO(con);
Vector v=pvo.getSomeRecord( " select a.* ,b.name from… where … " );
pvo.closeCon();
// 也可省略, ProcessVO 类重载了 finalize() ,在其中会自动关闭数据库联接。
2、 插入,例:
ProcessVO pvo=new ProcessVO(con);
boolean b =insertObjectRecord(tableName, map);
// 也可使用 int i=pvo.insertARecord("insert into …");
pvo.closeCon();
3、 更新,例:
ProcessVO pvo=new ProcessVO(con);
boolean b=pvo.updateARecord("table",map,new WhereString("key_id","=",id));
pvo.closeCon();
4、 删除,例:
ProcessVO pvo=new ProcessVO(con);
int i=pvo.delRecord(“delete from …”);
pvo.closeCon();
 
五、在 Web 中的应用,与Struts 完美结合
设数据库表如:
create table tel(
tel_id bigint primary key,
clerk_id bigint,
type varchar(8),
code varchar(32)
)
create table clerk(
clerk_id bigint primary key,
name varchar(32),
birthday varchar(10),
descreption varchar(255)
)
  本案可以与流行的 Struts 架构完美结合,使用时请将 pvotag.tld 复制到 WEB-INF 目录中。为了更方便地使用, cn.hkm.web.BaseMapForm 类继承了 Struts 中的 org.apache.struts.action.ActionForm ,并且重载了 reset 方法, 增加了一个Map record属性 ,只要您的 ActionForm 继承 BaseMapForm ,并按以下方式重载 reset 方法:
    public void reset(ActionMapping actionMapping,HttpServletRequest servletRequest) {
        super.reset(actionMapping,servletRequest);
}
这样,在理论上,除了上传文件外, 只要有这一个Map record属性,就足够了。
1、 查询,例:
ProcessVO pvo=new ProcessVO(con);
Vector v=pvo.getSomeRecord( " select a.* ,b.name from tel as a, clerk as b where a.clerk_id=b.clerk_id " );
session.setAttribute("clerk_tel_v",v);
     // 在页面中调用 Vector 结果集,以流行的 Struts 为例
     <%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>
        <%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
     <%@ taglib uri="/WEB-INF/pvotag.tld" prefix="pvo" %>
     ……..
      <table bgcolor="white" width="100%" cellpadding="0" cellspacing="1">
            <logic:present name="clerk_tel_v">
                <tr align=’center’>
<td> 姓名 </td>
<td> 分类 </td>
<td> 号码 </td>
</tr>
              <logic:iterate id="record" name="clerk_tel_v">
                <tr>
                  <td><bean:write name="record" property="name"/></td>
                  <td><bean:write name="record" property="type"/></td>
                  <td><bean:write name="record" property="code"/></td>
                </tr>
              </logic:iterate>
            </logic:present>
          </table>
 
如果表中有记录,则会有类似以下的结果:
姓名
分类
号码
张三
手机
13955668899
张三
电话
0553-6823888
张三
传真
0553-6823888
 
2、 数据录入(添加记录与编辑记录),例:
页面中的表单,
书写格式为 record. 字段名 的域,会自动成为 Map record 属性中的元素,其键名就是字段名,其键值就是域值。
       <p><h1 style="color:yellow"> 人员信息录入 </h1></p>
      <html:form action="/menuAction.do?method=clerk" method="post">
     <p>
             姓名            
           <html:hidden property="id"/>        
            <html:text property="record.name"/>
        </p>
     <p> 出生日期 <html:text property="record.birthday"/></p>
<p> 简介 <html:text property="record.descreption"/></p>
<p><html:submit> 提交 </html:submit></p>
</html:form>
 
/**MenuAction 中的 clerk 方法 */
public ActionForward clerk(ActionMapping actionMapping,
                                 ActionForm actionForm,
                                 HttpServletRequest servletRequest,
                                 HttpServletResponse servletResponse) {
String id=servletRequest.getParameter("id");
    ProcessVO pvo=new ProcessVO(con);
    MapForm form = (MapForm) actionForm;
    boolean b=false;  
    Map map=form.getRecord();// 获取表单中的记录
    if ((id == null)||id.equals("")){
     // 新插入一条记录
Long ID = pvo.insertKey("clerk", "clerk_id");       
        b=pvo.updateARecord("clerk",map,new WhereString("clerk_id", "=", ID));
        pvo.closeCon();
       if (b) {}
    }else {
// 更新一条记录
        pvo.setCon(con);
        b = pvo.updateARecord("clerk", map, new WhereString("clerk_id", "=", id));
        pvo.closeCon();
        if (b) {}
    }
// 在页面表单中,隐含域 <html:hidden property="id"/>
// 也可替换成 <html:hidden property="record.clerk_id"/> ,
// 但在更新数据时,请预先保存 clerk_id 值,如 String id=(Long)record.get(“clerk_id”).toString ,
// 然后调用 record.remove(“clerk_id”) ,
// 更新操作完毕后,调用 record.put(“clerk_id”,id) ,以便编辑记录使用。
// 原因是: updateARecord() 会自动将 map 中的所有元素作为 SQL 语句中的组
// 成部分,生成类似以下的语句:
//update clerk set clerk_id=?,name=?,birthday=?,descreption=?
//where (clerk_id = '123')
// 在 update 语句中, set 主键名 where 主键名 同时出现不被数据库支持
return actionMapping.findForward("clerk");
 }
 
/**clerk_edit 方法,从数据库中提取一条指定的记录,供表单编辑使用 */
public ActionForward clerk_edit(ActionMapping actionMapping,
                             ActionForm actionForm,
                             HttpServletRequest servletRequest,
                             HttpServletResponse servletResponse) {
    String id=servletRequest.getParameter("id");
    ProcessVO pvo=new ProcessVO(con);
    Map map=pvo.getARecord("clerk","clerk_id",id);   
    MapForm form = (MapForm) actionForm;
    form.setId(id);
    form.setRecord(map);
// 如果用常规的方式,准备数据是一件非常辛苦的工作。而用 PVO 时,是如此简单。
    return actionMapping.findForward("clerk");
}
 
请注意无论是插入一条新记录,还是更新一条记录以及为表单准备数据,操作都十分简洁。更值得一提的是,如果数据库表中的字段类型发生变化,不须修改 clerk 方法,如果表中增加了一些新的字段,也不须修改 clerk 方法,只要在表单中添加相应的属性。 假如:表中添加了新字段,
age int,
sex varchar(2),
在表单中添加以下两行即可:
<p> 年龄 <html:text property=" record.age "/></p>
<p> 性别 <html:text property=" record.sex "/></p>
注意!使用格式是: record. 字段名 。
 
《 HashMap 关系数据映射技术》源代码将在今后适当的时候公布。


凡是有该标志的文章,都是该blog博主Caoer(草儿)原创,凡是索引、收藏
、转载请注明来处和原文作者。非常感谢。

posted on 2006-05-21 17:11 草儿 阅读(964) 评论(1)  编辑  收藏 所属分类: java

Feedback

# re: HashMap关系数据映射技术(简称PVO技术) 2006-05-25 19:28 pc
http://www.kpwang.com/pc/view.jsp?board_id=1&article_id=200645223821
Java常见问题集锦(转载)

http://www.kpwang.com/pc/view.jsp?board_id=1&article_id=200645223641
java中的易混问题收集

http://www.kpwang.com/pc/view.jsp?board_id=1&article_id=20064522334
Java学习过程的一些重点  回复  更多评论