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

[SQL]:如何简化JDBC代码

作者:闵涛 文章来源:闵涛的学习笔记 点击数:1894 更新时间:2007/11/14 11:58:16
processor.process(rows); closeStmnt(stmnt); // 异常处理 } catch(SQLException e) { String message = "无法执行查询语句 " + sql; closeConn(conn); closeStmnt(stmnt); throw new DatabaseUpdateException(message); } }



上面的两个方法和处理查询的方法不同之处在于他们如何处理返回值。由于更新语句只需要返回被更新了的行数,所以我们不需要处理SQL操作返回的结果。实际上有些情况下连被更新了的行数都不需要返回,我们这样做的原因是在某些情况下需要确认更新操作已经完成。

我们设计了UpdateProcessor接口来处理Update操作返回的更新行数。

public interface UpdateProcessor {
  public void process(int rows);
}



例如在程序中需要保证更新操作,更新表中的至少一条记录。在UpdateProcessor接口的实现类中就可以加入对修改行数的检测,当没有记录被更新时,processor()方法可以抛出自定义的异常;也可以将更新的行数记录到日志文件中;或者激发一个自定义的更新事件。总而言之,你可以在其中做任何事。

下面是一个使用更新模型的例子:

首先生成SQL语句

private static final String SQL_UPDATE_USER = 
"UPDATE USERS SET USERNAME = ?, EMAIL = ? WHERE ID = ?";



实现UpdateProcessor接口。在Processor()方法中,检查Update操作是否更新了数据。如果没有,抛出IllegalStateException异常。

public class MandatoryUpdateProcessor implements UpdateProcessor {
  public void process(int rows) {
    if(rows < 1) {
      String message = "更新操作没有更新数据库表中的数据。";
      throw new IllegalStateException(message);
    }
  }
}



最后在updateUser()方法中执行Update操作并处理结果。

public static void updateUser(User user) {
  SQLProcessor sqlProcessor = new SQLProcessor();
  sqlProcessor.executeUpdate(SQL_UPDATE_USER,
                             new Object[] {user.getUserName(),
                                           user.getEmail(),
                                           new Integer(user.getId())},
                             new MandatoryUpdateProcessor());
}

 

事务模型

在数据库中,事务和独立的SQL语句的区别在于事务在生命期内使用一个数据库连接,并且AutoCommit属性必须被设为False。因此我们需要指定事务何时开始,何时结束,并且在事务结束时提交事务。我们可以重用SQLProcessor中的大部分代码来处理事务。也许在最开始读者会问为什么要把执行更新和处理更新的工作放在 executeUpdate()和handleUpdate()两个函数中完成--实际上它们是可以被合并到同一个函数中的。这样做的原因是把处理数据库连接的代码和处理SQL操作的代码分离开来。对于需要在多个SQL操作间共用数据库连接的事务模型来说,这种方案便于编码。

在事务中,我们需要保存事务的状态,特别是数据库连接的状态。前面的SQLProcessor中没有保存状态的属性,为了保证对SQLProcessor类的重用,我们设计了一个包装类,该类包装了SQLProcessor类,并且可以维护事务在生命周期内的状态。

public class SQLTransaction {
  private SQLProcessor sqlProcessor;
  private Connection conn;
  // 缺省构造方法,该方法初始化数据库连接,并将AutoCommit设定为False
  ...
  public void executeUpdate(String sql, Object[] pStmntValues,
                            UpdateProcessor processor) {
    // 获得结果。如果更新操作失败,回滚到事务起点并抛出异常
    try {
       sqlProcessor.handleUpdate(sql, pStmntValues, processor, conn);
    } catch(DatabaseUpdateException e) {
       rollbackTransaction();
       throw e;
    } 
  }
  public void commitTransaction() {
    // 事务结束,提交更新并回收资源
    try {
      conn.commit();
      sqlProcessor.closeConn(conn);
    // 如果发生异常,回滚到事务起点并回收资源
    } catch(Exception e) {
      rollbackTransaction();
      throw new DatabaseUpdateException("无法提交当前事务");
    }
  }
  private void rollbackTransaction() {
    // 回滚到事务起点并回收资源
    try {
      conn.rollback();
      conn.setAutoCommit(true);
      sqlProcessor.closeConn(conn);
    // 如果在回滚过程中发生异常,忽略该异常
    } catch(SQLException e) {
      sqlProcessor.closeConn(conn);
    }
  }
}



SQLTransaction中出现了一些新方法,这些方法主要是用来处理数据库连接和进行事务管理的。当一个事务开始时,SQLTransaction对象获得一个新的数据库连接,并将连接的AutoCommit设定为False,随后的所有SQL语句都是用同一个连接。

只有当commitTransaction()被调用时,事务才会被提交。如果执行SQL语句的过程中发生了异常,程序会自动发出一个回滚申请,以恢复程序对数据库所作的改变。对于开发人员来说,不需要担心在出现异常后处理回滚或关闭连接的工作。下面是一个使用事务模型的例子。

public static void updateUsers(User[] users) {
 // 开始事务
  SQLTransaction trans = sqlProcessor.startTransaction();
  // 更新数据
  User user = null;
  for(int i = 0; i < users.length; i++) {
    user = users[i];
    trans.executeUpdate(SQL_UPDATE_USER,
                       new Object[] {user.getUserName(),
                                     user.getFirstName(),
                                     user.getLastName(),
                                     user.getEmail(),
                                     new Integer(user.getId())},
                       new MandatoryUpdateProcessor());
  }
  // 提交事务
  trans.commitTransaction();
}



在例子中我们只使用了更新语句(在大多数情况下事务都是由更新操作构成的),查询语句的实现方法和更新语句类似。

问题

在实际使用上面提到的这些模型时,我遇到了一些问题,下面是这些问题的小结,希望对大家有所帮助。

自定义数据库连接

在事务处理的时候,有可能发生在多个事务并存的情况下,它们使用的数据库连接不同的情况。ConnectionManager需要知道它应该从数据库连接池中取出哪一个连接。你可以简单修改一下模型来满足上面的要求。例如在executeQuery()和executeUpdate()方法中,你可以把数据库连接作为参数,然后将它们传送给ConnectionManager对象。请记住所有的连接管理都应该放在executeXXX()方法中。另外一种解决方案,也是一种更面向对象化的解决方案,是将一个连接工厂作为参数传递给SQLProcessor的构造函数。对于不同的连接工厂类型,我们需要不同的SQLProcessor对象。

ResultProcessor类的返回值:对象数组还是List?

为什么ResultProcessor接口中的process()方法返回的是对象数组呢?怎么不使用List类呢?这是由于在很多实际的应用中,SQL查询在大多数情况下值返回一行数据,在这种情况下,使用List对象会有些多余了。但是如果你确信SQL查询将返回多行结果,你可以使用List对象。

数据库操作异常

我们可以用多个自定义的数据库操作异常类来替代运行时发生的SQLException异常。最好在这些自定义的异常类时继承RuntimeException类,这样可以将这些异常进行集中处理。也许你会认为因该将异常处理放在发生异常的地方。但是我们设计这个的模型的目的之一是在JDBC应用程序开发中去掉或弱化异常处理的部分,只有使用RuntimeException我们才可能达到这个目的。


 

 

 

 

 

上一页  [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……
    咸宁网络警察报警平台