代码改变世界

9月22日培训日记(上)

2006-09-23 22:41  java ee spring  阅读(215)  评论(0编辑  收藏  举报

首先检查昨天的作业,了解学员对昨天讲解知识的掌握情况。
(1)根据马献忠完成的BasicDataSourceFactory.createDataSource(Properties properties) 方法中设置的properties对象,询问他是怎么知道该如何设置properties对象的,我给大家分析了properties对象中的关键字就是根据BasicDataSource的bean属性来的原因。
(2)检查魏奕东完成的作业情况,下面是他的程序代码
package cn.itcast;

import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;
import com.ibatis.common.jdbc.SimpleDataSource;

public class SimpleDataSourceDemo {

 public static void main(String[] args) {

  Connection conn = null;
  PreparedStatement pstmt = null;
  ResultSet rs = null;
  
  Properties props = new Properties();
  InputStream ips = InputStream.class.getResourceAsStream("/" + "config.properties");
  try {
   props.load(ips);
  } catch (Exception e) {
   e.printStackTrace();
   return;
  }finally{
   try{
    ips.close();
    ips = null;
   }catch(Exception e){
    e.printStackTrace();
   }
  }

  try {

   SimpleDataSource simpleDS = new SimpleDataSource(props);
   conn = simpleDS.getConnection();
   pstmt = conn.prepareStatement("select * from pet where species='dog'");
   rs = pstmt.executeQuery();
   
           if(!rs.next()){
             System.out.println("No record!");
           }
            else{
             rs.beforeFirst();//非滚动结果集而不抛异常,不知其故。
    while (rs.next()) {
     System.out.println("NAME:" + rs.getString("name") +
                  "/tOWNER:"+ rs.getString("owner") +
                  "/tBIRTH:" + rs.getString("birth"));
    }
            }
  } catch (Exception e) {
   e.printStackTrace();
  }finally{
   if(rs != null){
             try {
     rs.close();
    } catch (SQLException e) {
     e.printStackTrace();
    }
             rs = null;
   }
         if(rs != null){
          try {
     pstmt.close();
    } catch (SQLException e) {
     e.printStackTrace();
    }
         }
         if(conn != null){
             try {
     conn.close();
    } catch (SQLException e) {
     e.printStackTrace();
    }
         }
  }
 }

}

总体上来说,魏奕东做得不错,接着魏奕东针对他上面的程序向我提了一个问题,与问题相关的代码如下:
           if(!rs.next()){
             System.out.println("No record!");
           }
            else{
             rs.beforeFirst();//非滚动结果集而不抛异常,不知其故。
  while (rs.next()) {
   System.out.println("NAME:" + rs.getString("name") +
     "/tOWNER:"+ rs.getString("owner") +
     "/tBIRTH:" + rs.getString("birth"));
  }
            }

他从JDK文档中看到:对于非滚动结果集调用beforeFirst方法,应该抛出异常,可是他使用的就是默认的不可滚动的结果集,怎么对这个结果集调用beforeFirst方法不抛出异常。
我先没有直接回答他的这个问题,而是挑出了他程序中的一个大败笔。他上面的程序是先调用rs.next判断是否有记录,如果有记录,再打印出所有记录。在打印所有记录时,他也意识到了游标已移动到第一行,所以,再使用rs.beforeFirst()方法将游标移回到第一行之前,再按照通常的方式对整个结果集进行遍历处理。我笑话他说:“他在走路时,先迈出一步试了试路是否可走,如果可以走,他又退回到起点,然后再向前走;他为何不迈出一步后,发现路可走时,接着迈出的第一步继续往前走呢?”,同学们都哈哈大笑,点头称是,但代码怎么写?我针对魏奕东的代码,给出了如下建议:
 do
 {
  ...
 }while(rs.next());

再回过头来说为什么不可滚动的结果集调用beforeFirst时,没有抛出异常。我分析两种可能的原因:a.可能是某种驱动程序的原因,换个数据库驱动程序试试;b.在很久以前,要产生可滚动结果集,是一种特殊功能,而对现在的驱动程序来说,这是一项基本功能,只要产生结果集,就是可滚动的,这就好比以前的彩电要带遥控功能需要特殊定制,而现在只要是台彩电,就具有遥控功能,遥控成了彩电的基本配置,要想弄台没有遥控功能的彩电,还弄不到了呢!JDBC规范为了向前兼容,要保留这个参数设置和文档说明,但各个驱动厂商会忽略这点现在看来毫无意义的要求和建议。

针对魏奕东的问题,我补充讲解了可滚动,可更改,保持光标的结果集,主要就是分析了Connection.createStatement(int resultSetType,int resultSetConcurrency,int resultSetHoldability)中的各个参数的作用和各个参数的各种设置值的意义。接着,我又要魏奕东将结果集类型强制设置成ResultSet.TYPE_FORWARD_ONLY,然后看实验结果,他报告在这种情况下,结果集还是可以滚动,看来现在真是难以弄出不可滚动的结果集了,这就像我们难以再弄台没有遥控功能的彩电的道理。然后,我讲解了如何使用可更改的结果集来更改、插入和删除底层数据库中的记录。
为了讲清楚resultSetHoldability这个参数,我又为大家补充了JDBC中的事务处理问题,给出了如下示意代码:
try
{
 cn.setAutoCommit(false);
 stmt.executeUpdate();
 stmt.exectueUpdate();
 rs = stmt.executeQuerey();
 rs.next();
 cn.commit();
 rs.next(); //用于测试resultSetHoldability这个参数
}
catch(Exception e)
{
 cn.roolback();
}

在上午下课时,临时为同学们布置了一道作业题:通过自己的实验来了解JDBC中的事务处理,了解“可滚动,可更改,保持光标的结果集”的应用。
后面的内容还很多,留在“9月22日培训日记(下)”中续写............