9.2  JDBC API 2.0 简介
9.2.1  新的记录集接口(ResultSet接口)
1 新定义了若干个常数
这些常数用于指定ResultSet的类型 游标移动的方向等性质 如下所示 
public static final int FETCH_FORWARD;
public static final int FETCH_REVERSE;
public static final int FETCH_UNKNOWN;
public static final int TYPE_FORWARD_ONLY;
public static final int TYPE_SCROLL_INSENSITIVE;
public static final int TYPE_SCROLL_SENSITIVE;
public static final int CONCUR_READ_ONLY;
public static final int CONCUR_UPDATABLE;
FETCH_FORWORD 该常数的作用是指定处理记录集中行的顺序是由前到后 即从第一行开始处理 一直到最后一行 
FETCH_REVERSE 该常数的作用是指定处理记录集中行的顺序是由后到前 即从后一行开始处理 一直到第一行 
FETCH_UNKNOWN 该常数的作用是不指定处理记录集中行的顺序 由 JDBC 驱动程序和数据库系统决定 
TYPE_FORWARD_ONLY 该常数的作用是指定数据库游标的移动方向是向前 不允许向后移动 即只能使用ResultSet接口的next()方法 而不能使用 previous()方法 否则会产生错误 
TYPE_SCROLL_INSENSITIVE 该常数的作用是指定数据库游标可以在记录集中前后
移动 并且当前数据库用户获取的记录集对其他用户的操作不敏感 就是说 当前用户正
在浏览记录集中的数据 与此同时 其他用户更新了数据库中的数据 但是当前用户所获
取的记录集中的数据不会受到任何影响 
TYPE_SCROLL_SENSITIVE 该常数的作用是指定数据库游标可以在记录集中前后移动 并且当前数据库用户获取的记录集对其他用户的操作敏感 就是说 当前用户正在浏览记录集 但是其它用户的操作使数据库中的数据发生了变化 当前用户所获取的记录集中的数据也会同步发生变化 这样有可能会导致非常严重的错误产生 建议慎重使用该常数 
CONCUR_READ_ONLY 该常数的作用是指定当前记录集的协作方式(concurrency mode)为只读 一旦使用了这个常数 那么用户就不可以更新记录集中的数据  CONCUR_UPDATABLE 该常数的作用是指定当前记录集的协作方式(concurrency mode)为可以更新 一旦使用了这个常数 那么用户就可以使用 updateXXX()等方法更新记录集中的数据 
2 ResultSet接口提供了一整套的定位方法
这些可以在记录集中定位到任意一行 具体有 
public boolean absolute(int  row);  该方法的作用是将记录集中的某一行设定为当前行 亦即将数据库游标移动到指定的行 参数 row指定了目标行的行号 这是绝对的行号由记录集的第一行开始计算 不是相对的行号 
public boolean relative(int  rows);  该方法的作用也是将记录集中的某一行设定为当前行 但是它的参数 rows表示目标行相对于当前行的行号 例如当前行是第3行 现在需要移动到第5行去 既可以使用absolute()方法 也可以使用 relative()方法 代码如下 
例 
rs.absolute(5);
或者
rs.relative(2);
其中rs代表ResultSet接口的实例对象 
又如当前行是第5行 需要移动到第 3行去 代码如下 
例 
rs.absolute(3);
或者
rs.relative(-2);
其中rs代表ResultSet接口的实例对象 
读者需要注意的问题是 传递给 relative()方法的参数 如果是正数 那么数据库游标向前移动 如果是负数 那么数据库游标向后移动 
注意 在本章中所说的数据库游标向前移动是指向行号增大的方向移动 向后移动是指向行号减少的方向移动 
public boolean first();  该方法的作用是将当前行定位到数据库记录集的第一行 
public boolean last();  该方法的作用刚好和 first()方法相反 是将当前行定位到数据库记录集的最后一行 
public boolean isFirst();  该方法的作用是检查当前行是否记录集的第一行 如果是返回true 否则 返回false 
public boolean isLast();   该方法的作用是检查当前行是否记录集的最后一行 如果是 返回true 否则 返回false 
public void afterLast();  该方法的作用是将数据库游标移到记录集的最后 位于记录集最后一行的后面 如果该记录集不包含任何的行 该方法不产生作用 
public void beforeFirst();   该方法的作用是将数据库游标移到记录集的最前面 位于记录集第一行的前面 如果记录集不包含任何的行 该方法不产生作用 
public boolean isAfterLast();  该方法检查数据库游标是否处于记录集的最后面 如果是 返回true 否则 返回false 
public boolean isBeforeFirst();  该方法检查数据库游标是否处于记录集的最前面 如果是 返回true 否则 返回false 
public boolean next();  该方法的作用是将数据库游标向前移动一位 使得下一行成为当前行 当刚刚打开记录集对象时 数据库游标的位置在记录集的最前面 第一次使用 next()方法 将会使数据库游标定位到记录集的第一行 第二次使用 next()方法 将会使数据库游标定位到记录集的第二行 以此类推 
注意 如果在当前行打开了一个输入流(Input Stream) 那么再次使用 next()方法时将会自动关闭该输入流 
public boolean previous();  该方法的作用是将数据库游标向后移动一位 使得上一行成为当前行 
3 ResultSet接口添加了对行操作的支持
使用JDBC API 2.0 不仅可以任意将数据库游标定位到记录集中的特定行 而且还可以使用ResultSet接口新定义的一套方法更新当前行的数据 在以前 如果Java程序员希望更新记录集中某行的数据 必须发送 SQL 语句给数据库 程序员需要在 Java 代码中嵌入冗长的SQL语句 用以执行 UPDATE DELETE INSERT 等数据库操作 但是 当JDBC API 2.0 出现时 一切就都改变了 程序员已经可以部分抛开 SQL语言 享受Java编程的乐趣了 ResultSet接口中新添加的部分方法如下所示 
public boolean rowDeleted();  如果当前记录集的某行被删除了 那么记录集中将会留
出一个空位 调用rowDeleted()方法 如果探测到空位的存在 那么就返回 true 如果没有探测到空位的存在 就返回false值 
public boolean rowInserted();   如果当前记录集中插入了一个新行 该方法将返回true 否则返回false 
public boolean rowUpdated();   如果当前记录集的当前行的数据被更新 该方法返回true 否则返回false 
public void insertRow();   该方法将执行插入一个新行到当前记录集的操作 
public void updateRow();   该方法将更新当前记录集当前行的数据 
public void deleteRow();  该方法将删除当前记录集的当前行 
public void updateString(int columnIndex String x);  该方法更新当前记录集当前行某列的值 该列的数据类型是 String(指 Java 数据类型是 String 与之对应的 JDBC 数据类型是VARCHAR或NVARCHAR 等数据类型) 该方法的参数 columnIndex指定所要更新的列的列索引 第一列的列索引是 1 以此类推 第二个参数 x 代表新的值 这个方法并不执行数据库操作 需要执行 insertRow()方法或者 updateRow()方法以后 记录集和数据库中的数据才能够真正更新 
public void updateString(String    columnName String    x);  该方法和上面介绍的同名方法差不多 不过该方法的第一个参数是 columnName 代表需要更新的列的列名 而不是columnIndex 
ResultSet 接口中还定义了很多个 updateXXX()方法 都和上面的两个方法相类似 由于篇幅的原因 在这里就不详细描述了 对此感兴趣的读者 可以参考相关的文献 
往数据库当前记录集插入新行的操作流程如下 
1 调用moveToInsertRow()方法 
2 调用updateXXX()方法 指定插入行各列的值 
3 调用insertRow()方法 往数据库中插入新的行 

更新数据库中某个记录的值(某行的值)的方法是 
1 定位到需要修改的行(使用 absolute() relative()等方法定位) 
2 使用相应updateXXX()方法设定某行某列的新值 XXX 所代表的Java 数据类型
必须可以映射为某列的JDBC数据类型 如果希望rollback该项操作 请再调用updateRow()方法以前使用cancelRowUpdates()方法 这个方法可以将某行某列的值复原 
3 使用updateRow()方法 完成 UPDATE 的操作 
删除记录集中某行(亦即删除某个记录)的方法 
1 定位到需要修改的行(使用 absolute() relative()等方法定位) 
2 使用deleteRow()方法 
4 新的ResultSet接口添加了对 SQL3数据类型的支持
5 获取记录集行数的方法
1 首先使用last()方法 将数据库游标定位到记录集的最后一行 
2 使用 getRow()方法 返回记录集最后一行的行索引 该索引就等于记录集所包
含记录的个数 也就是记录集的行数
9.2.2  新的SQL语句接口(Statement 接口)
在JDBC API 2.0 中 SQL语句接口(Statement接口)也有了很大的改进 功能更加强大  PreparedStatement接口和CallableStatement接口都继承了 Statement接口 因此本小节也介绍这两个接口相对于 JDBC API 1.0的改进之处 因为上述的三个接口都由Connection接口的方法创建 所以本小节也顺便提一提 Connection接口 
1 Statement接口 CallableStatement接口 PreparesStatement接口的创建
这三个接口分别由Connection接口的createStatement() prepareStatement() prepareCall()等方法创建 这几个方法的定义如下 
public Statement createStatement();
public Statement createStatement(int resultSetType int resultSetConcurrency);
public CallableStatement prepareCall(String sql);
public CallableStatement prepareCall(String sql int resultSetType 
int resultSetConcurrency);
public PreparedStatement prepareStatement(String sql);
public PreparedStatement prepareStatement(String sql int resultSetType 
 int resultSetConcurrency);
上面列出的方法中
参数sql代表需要执行的 SQL语句  这些 SQL语句不是完整的
SQL 语句 一般带有 IN/OUT/INOUT 参数 参数 resultSetType 代表该方法创建的 SQL 语句接口执行 SQL 语句所返回的 ResultSet 的类型 例如 是否允许数据库游标前后移动是否对其他用户的数据库更新操作敏感等 它们都是一些整型的常数 在ResultSet接口中定义了
参数 resultSetConcurrency 代表该方法创建的SQL语句接口执行SQL语句所返回的ResultSet的协同模式 如允许更新记录集的数据 或者仅仅只读 不能更新等 它们也是一些整型的常数 在ResultSet接口中定义了
例 
stmt=con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE 
ResultSet.CONCUR_UPDATABLE);
上面的代码创建了一个 SQL语句接口(Statement)的实例对象 该实例对象允许它执行
SQL语句所返回的记录集中的数据库游标前后移动 允许更新记录集中的数据 
2 支持批操作
Statement接口 PreparedStatement接口 CallableStatement接口都支持数据库批操作就是将若干个 SQL 语句添加到一个 SQL 语句块(Batch)中 一并发送到数据库服务器去数据库引擎执行完 SQL语句块中的语句后 会将所有的结果一并返回 这种功能特别适用于大批量的数据库 INSERT 操作 为了实现这样的功能 必须用到的 Statement接口的方法
如下所示 
public void addBatch(String  sql);  该方法用于将SQL语句添加到 SQL语句块中 
public void clearBatch();   该方法用于将SQL语句块中的所有SQL语句全部删除 
public int[] executeBatch();  该方法用于将 SQL语句块发送到数据库服务器去 并执
行它 返回的结果是一个整型数组 数组中的元素是数据库服务器执行 SQL语句块中SQL语句所返回的更新计数 SQL语句块中含有多少个 SQL语句 返回的整行数组中就含有多少个元素 
使用JDBC API执行数据库批操作的方法是 
1 创建Statement接口的实例对象 
2 调用addBatch()方法 往SQL语句块中添加若干个SQL语句 
3 使用executeBatch()方法 完成数据库批操作

上面介绍的执行数据库批操作的方法仅仅适用于 Statement 接口 不适用于
PreparedStatement接口 CallableStatement接口 后面两个接口定义了新的 addBatch()方法
该方法不需要任何参数 但是在Statement接口中定义的 addBatch()方法却需要参数 参数是一个SQL语句 数据类型是String 
在 PreparedStatement接口 CallableStatement接口中实现数据库批操作的方法是 
1 创建PreparedStatement接口或者CallableStatement接口的实例对象 
2 使用PreparedStatement 接口中定义的 setXXX()方法设定 SQL语句(该 SQL语句是在创建 PreparedStatement 接口或者 CallableStatement 接口的实例对象时初始化的)的IN/OUT/INOUT 参数的值(CallableStatement 接口并没有定义任何 setXXX()方法 它的setXXX()方法全部继承自PreparedStatement接口)  
3 使用executeBatch()方法该方法在Statement接口中定义不过PreparedStatement
接口和CallableStatement接口都继承了这个方法