转至繁体中文版     | 网站首页 | 图文教程 | 资源下载 | 站长博客 | 图片素材 | 武汉seo | 武汉网站优化 | 
最新公告:     敏韬网|教学资源学习资料永久免费分享站!  [mintao  2008年9月2日]        
您现在的位置: 学习笔记 >> 图文教程 >> 数据库 >> Sql Server >> 正文
[SQL]:如何简化JDBC代码         

[SQL]:如何简化JDBC代码

作者:闵涛 文章来源:闵涛的学习笔记 点击数:1885 更新时间:2007/11/14 11:58:16

问题的提出

在一个应用程序中,处理JDBC的操作是一个重复率较高的工作。当你在一个JDBC数据源上执行SQL查询时,你通常需要执行下面几个步骤:

1.生成SQL语句

2.获得连接

3.获得一个PreparedStatement对象

4.在PreparedStatement对象中设定需要送入到数据库的值

5.执行SQL语句

6.处理查询结果

除此之外,你还需要处理SQLException异常。如果上面列出的这些步骤分散在程序的各个部分的话,程序中需要多个try/catch块来处理异常。

如果我们仔细看看上面列出的步骤,就会发现在执行不同的SQL语句时,上面这些步骤中涉及到的程序代码变化不会很大:我们使用同样的方法获得数据库连接和PreperedStatement对象;使用setXXX方法来设定PreperedStatement对象中的值;处理SQL查询结果的过程也是基本不变的。在这篇文章中,我们通过定义三个JDBC模型,去除了上述六个步骤中的三个步骤,这样使得整个过程更加简单,而且具有更好的通用性。

查询模型

我们定义了一个名叫SQLProcessor的类,在该类中定义了一个executeQuery()方法来执行SQL语句,我们在实现这个方法的时候尽量保持代码的简洁性,并且传递尽可能少的参数给该方法。下面是该方法的定义:

public Object[] executeQuery(String sql, Object[] pStmntValues,
                             ResultProcessor processor);



我们知道在执行SQL语句的JDBC过程中,变化的因素有三个:SQL语句,PreparedStatement对象和如何解释和处理查询结果。在上面的方法定义中,sql中保存的就是SQL语句;pStmntValues对象数组保存的是需要放入preparedStatement对象中的值;processor参数是一个能够处理查询结果的对象,于是我们把JDBC程序涉及到的对象分成了三个部分。下面让我们来看一下executeQuery()和与它相关的一些方法的实现:

public class SQLProcessor {
  public Object[] executeQuery(String sql, Object[] pStmntValues,
                               ResultProcessor processor) {
    //获得连接
    Connection conn = ConnectionManager.getConnection();
    //将SQL语句的执行重定向到handlQuery()方法
    Object[] results = handleQuery(sql, pStmntValues, processor, conn);
    //关闭连接
    closeConn(conn);
    //返回结果
    return results;
  }
  protected Object[] handleQuery(String sql, Object[] pStmntValues,
                     ResultProcessor processor, Connection conn) 
{
    //获得一个preparedStatement对象
    PreparedStatement stmnt = null;
    try {
      //获得preparedStatement
      stmnt = conn.prepareStatement(sql);
      //向preparedStatement中送入值
      if(pStmntValues != null) {
        PreparedStatementFactory.buildStatement(stmnt, pStmntValues);
      }
      //执行SQL语句
      ResultSet rs = stmnt.executeQuery();
      //获得查询结果
      Object[] results = processor.process(rs);
      //关闭preparedStatement对象
      closeStmnt(stmnt);
      //返回结果
      return results;
      //处理异常
      } catch(SQLException e) {
        String message = "无法执行查询语句 " + sql;
        //关闭所有资源
        closeConn(conn);
        closeStmnt(stmnt);
        //抛出DatabaseQueryException
        throw new DatabaseQueryException(message);
      }
    }
  }
...
}



程序中有两个方法需要说明:PreparedStatementFactory.buildStatement()和processor.process()。buildStatement()方法把在pStmntValues对象数组中的所有对象送到prepareStatement对象中的相应位置。例如:

...
//取出对象数组中的每个对象的值,
//在preparedStatement对象中的相应位置设定对应的值
for(int i = 0; i < values.length; i++) {
  //如果对象的值为空, 设定SQL空值
  if(value instanceof NullSQLType) {
    stmnt.setNull(i + 1, ((NullSQLType) value).getFieldType());
  } else {
    stmnt.setObject(i + 1, value);
  }
}

因为stmnt.setOject(int index, Object value)方法不能接受一个空对象作为参数。为了使程序能够处理空值,我们使用了自己设计的NullSQLType类。当一个NullSQLType对象被初始化的时候,将会保存数据库表中相应列的SQL类型。在上面的例子中我们可以看到,NULLSQLType对象的属性中保存了一个SQL NULL实际对应的SQL类型。我们用NULLSQLType对象的getFieldType()方法来向preparedStatement对象填入空值。

下面让我们来看一看processor.process()方法。Processor类实现了ResultProcessor接口,该接口是用来处理SQL查询结果的,它只有一个方法process(),该方法返回了处理SQL查询结果后生成的对象数组。

public interface ResultProcessor {
  public Object[] process(ResultSet rs) throws SQLException;
}


process()的典型实现方法是遍历查询后返回的ResultSet对象,将保存在ResultSet对象中的值转化为相应的对象放入对象数组。下面我们通过一个例子来说明如何使用这些类和接口。例如当我们需要从数据库的一张用户信息表中取出用户信息,表名称为User:

列名 数据类型 ID NUMBER UserName VARCHAR2 Email VARCHAR2



我们需要在程序中定义一个类User来映射上面的表:

public User(int id, String userName, String email)


如果我们使用常规方法来读取User表中的数据,我们需要一个方法来从数据库表中读取数据,然后将数据送入User对象中。而且一旦查询语句发生变化,我们需要修改大量的代码。让我们看一看采用本文描述的解决方案情况会如何。

首先构造一个SQL语句。

private static final String SQL_GET_USER = "SELECT * FROM USERS WHERE ID = ?";


然后创建一个ResultProcessor接口的实例类,通过它我们可以从查询结果中获得一个User对象。

public class UserResultProcessor implements ResultProcessor {
  // 列名称定义(省略)
  ...
  public Object[] process(ResultSet rs) throws SQLException {
    // 使用List对象来保存所有返回的User对象
    List users = new ArrayList();
    User user = null;
    // 如果查询结果有效,处理查询结果
    while(rs.next()) {
      user = new User(rs.getInt(COLUMN_ID), rs.getString(COLUMN_USERNAME),
                      rs.getString(COLUMN_EMAIL));
      users.add(user);
    }
    return users.toArray(new User[users.size()]);


最后,将执行SQL查询和返回User对象的指令放入getUser()方法中。

public User getUser(int userId) {
  // 生成一个SQLProcessor对象并执行查询
  SQLProcessor processor = new SQLProcessor();
  Object[] users = processor.executeQuery(SQL_GET_USER_BY_ID,
                                          new Object[] {new Integer(userId)},
                                          new UserResultProcessor());
  // 返回查询到的第一个User对象
  return (User) users[0];
}

这就是我们需要做的全部工作:只需要实现一个processor类和一个getUser()方法。与传统的JDBC程序相比,在本文描述的模型中,我们不需要处理数据库连接操作,生成prepareStatement对象和异常处理部分的代码。如果需要在同一张表中根据用户名查用户ID,我们只需要在代码中申明新的查询语句,然后重用UserResultProcessor类中的大部分代码。

更新模型

如果SQL语句中涉及到更新,情况又会怎样呢?我们可以用类似于设计查询模型的方法来设计更新模型,我们需要向SQLProcessor类中增加一些新的方法。这些方法同executeQuery()和handleQuery()方法有相似之处,只是我们需要改变一下处理ResultSet对象的代码,并且把更新的行数作为方法的返回值。

public void executeUpdate(String sql, Object[] pStmntValues,
                          UpdateProcessor processor) {
  // 获得数据库连接
  Connection conn = ConnectionManager.getConnection();
  // 执行SQL语句
  handleUpdate(sql, pStmntValues, processor, conn);
  // 关闭连接
  closeConn(conn);
}
protected void handleUpdate(String sql, Object[] pStmntValues,
                            UpdateProcessor processor, Connection conn) {
  PreparedStatement stmnt = null;
  try {
  stmnt = conn.prepareStatement(sql);
  // 向prepareStatement对象中送入值
  if(pStmntValues != null) {
    PreparedStatementFactory.buildStatement(stmnt, pStmntValues);
  }
  // 执行更新语句
  int rows = stmnt.executeUpdate();
  // 统计有多少行数据被更新
  

[1] [2]  下一页


[办公软件]在sybase中插入图片、PDF、文本文件  [办公软件]安装Sybase ASE
[办公软件]linux指令大全(完整篇)  [办公软件]Linux新手入门常用命令大全
[办公软件]在RedHat Linux 9里安装gaim0.80  [办公软件]浅谈Linux 下Java 1.5 汉字方块问题解决方法
[办公软件]Linux程序员必读:中文化与GB18030标准  [办公软件]linux指令大全
[办公软件]制作Linux启动盘的四种方法  [办公软件]Linux文件系统的反删除方法
教程录入:mintao    责任编辑:mintao 
  • 上一篇教程:

  • 下一篇教程:
  • 【字体: 】【发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口
      注:本站部分文章源于互联网,版权归原作者所有!如有侵权,请原作者与本站联系,本站将立即删除! 本站文章除特别注明外均可转载,但需注明出处! [MinTao学以致用网]
      网友评论:(只显示最新10条。评论内容只代表网友观点,与本站立场无关!)

    同类栏目
    · Sql Server  · MySql
    · Access  · ORACLE
    · SyBase  · 其他
    更多内容
    热门推荐 更多内容
  • 没有教程
  • 赞助链接
    更多内容
    闵涛博文 更多关于武汉SEO的内容
    500 - 内部服务器错误。

    500 - 内部服务器错误。

    您查找的资源存在问题,因而无法显示。

    | 设为首页 |加入收藏 | 联系站长 | 友情链接 | 版权申明 | 广告服务
    MinTao学以致用网

    Copyright @ 2007-2012 敏韬网(敏而好学,文韬武略--MinTao.Net)(学习笔记) Inc All Rights Reserved.
    闵涛 投放广告、内容合作请Q我! E_mail:admin@mintao.net(欢迎提供学习资源)

    站长:MinTao ICP备案号:鄂ICP备11006601号-18

    闵涛站盟:医药大全-武穴网A打造BCD……
    咸宁网络警察报警平台