stmt.executeUpdate("CREATE TABLE Sells " +
"(bar VARCHAR2(40), beer VARCHAR2(40), price REAL)" );
stmt.executeUpdate("INSERT INTO Sells " +
"VALUES ('Bar Of Foo', 'BudLite', 2.00)" );
String sqlString = "CREATE TABLE Bars " +
"(name VARCHAR2(40), address VARCHAR2(80), license INT)" ;
stmt.executeUpdate(sqlString);
由于SQL语句并非恰好为一个字符串(或适合写在一行),所以需要使用加号(+)连结。特别注意在字符串"INSERT INTO Sells"后面的空格,为的是与字符串"VALUES"分开。
当使用executeUpdate执行DDL语句,返回值总是零(zero),当执行数据修改语句时将返回大于等零的值,即被修改的记录数。
int n = prepareUpdatePrice.executeUpdate() ;
________________________________________
执行 SELECT 语句
相对于前面的执行语句(DDL),查询语句执行后返回一个结果集合,并且不改变数据库的状态。相应地使用另一个方法executeQuery,返回一个ResultSet对象:
String bar, beer ;
float price ;
ResultSet rs = stmt.executeQuery("SELECT * FROM Sells");
while ( rs.next() ) {
bar = rs.getString("bar");
beer = rs.getString("beer");
price = rs.getFloat("price");
System.out.println(bar + " sells " + beer + " for " + price + " Dollars.");
}
查询语句返回的结果集被放在一个ResultSet实例中。我们可以访问结果集中的每一行记录(record)及每一行记录的属性。ResultSet提供一个游标(cursor),用于访问它的每一行记录。游标开始时指示在第一条记录的前面。可以使用next方法使游标指向下一条记录,如果下一条记录存在,next方法返回真(true),否则返回假(false)。
我们可以使用相应类型的getXXX方法获取某一行记录。在前面的示例中,我们用的是getString和getFloat方法访问某一列的值。我们需要提供列的名称作为方法的参数,并且注意VARCHAR2类型的bar、beer被转换成Java的String、REAL被转换成Java的float。
我们还可以使用列的顺序号代替列的名称来访问结果集,示范如下:
bar = rs.getString(1);
price = rs.getFloat(3);
beer = rs.getString(2);
________________________________________
访问ResultSet
JDBC还提供一套方法,让您得到游标当前处于结果集的位置,如getRow, isFirst, isBeforeFirst, isLast, isAfterLast。
这意味着游标允许自由访问结果集。默认的,游标只能向前滚动并且是只读的。当连接(Connection)建立了语句(Statement)后,您可以灵活地改变结果集(ResultSet)的滚动及更新模式。
Statement stmt = con.createStatement(
ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
ResultSet rs = stmt.executeQuery("SELECT * FROM Sells");
不同的选项包括: TYPE_FORWARD_ONLY、TYPE_SCROLL_INSENSITIVE和TYPE_SCROLL_SENSITIVE。您可以在需要只读游标时选用CONCUR_READ_ONLY、需要更新时选用CONCUR_UPDATABLE。默认的游标可以使用rs.next()向前滚动。使用可滚动的游标,您有更多的操作,示范如下:
rs.absolute(3); // 滚动到结果集的第三行
rs.previous(); // 回滚一行(第二行)
rs.relative(2); // 向前滚动两行(第四行)
rs.relative(-3); // 回滚三行(第一行)
________________________________________
事务(Transactions)
JDBC允许多条SQL语句作为一个事务。因此使用JDBC事务,我们能确保ACID (Atomicity, Consistency, Isolation, Durability)属性。
连接建立后,默认的事务模式是自动提交(auto-commit)。这使每一条SQL语句都被当作一个事务来处理。
我们可以关闭自动提交事务模式,如下:
con.setAutoCommit(false) ;
再次打开自动提交事务模式:
con.setAutoCommit(true) ;
一旦自动提交模式被关闭,除非您明确地使用commit()方法提交,否则每一条SQL语句都不会被提交。
con.commit() ;
在执行commit()方法之前,我们可以随时使用rollback()方法来回滚事务,取消之前的操作。
举例如下:
con.setAutoCommit(false);
Statement stmt = con.createStatement();
stmt.executeUpdate("INSERT INTO Sells VALUES('Bar Of Foo', 'BudLite', 1.00)" );
con.rollback();
stmt.executeUpdate("INSERT INTO Sells VALUES('Bar Of Joe', 'Miller', 2.00)" );
con.commit();
con.setAutoCommit(true);
请读者逐句理解上面的例子吧。
通常,事务回滚结合Java异常机制,被用于处理(不)可预见的错误。下一节我们将介绍Java的异常机制。
________________________________________
Handling Errors with Exceptions
错误无处不在。为保证程序的可恢复性,让数据库不至于由于某个错误导致崩溃。事务回滚与Java的异常机制提供了很优雅的解决办法。
客户(program)访问服务器(database)需要获得服务器的任务错误反馈。JDBC提供了SQLException用于访问这些错误。
结束事务回滚,举一个异常的例子:
try {
con.setAutoCommit(false) ;
stmt.executeUpdate("CREATE TABLE Sells (bar VARCHAR2(40), " +
"beer VARHAR2(40), price REAL)") ;
stmt.executeUpdate("INSERT INTO Sells VALUES " +
"('Bar Of Foo', 'BudLite', 2.00)") ;
con.commit() ;
con.setAutoCommit(true) ;
}catch(SQLException ex) {
System.err.println("SQLException: " + ex.getMessage()) ;
con.rollback() ;
con.setAutoCommit(true) ;
}
在上例中,由于beer被定义为VARHAR2(拼写错误),导致一个异常被抛出。错误的输出如下:
Message: ORA-00902: invalid datatype
假如您纠正了数据类型的错误,也可能会发生空间不足的错误,使您不能够建立一个新表。
需要对照原文,请访问:http://www-db.stanford.edu/~ullman/fcdb/oracle/or-jdbc.html