| 到目前为止您还只看到了一些代码段。稍后在本节您将看到一些可运行的、完整的示例应用程序。
第一个示例代码创建COFFEES表;第二个示例代码在表中插入一些数据并输出查询结果。第三个应用程序创建SUPPLIERS表,第四个应用程序在SUPPLIERS表中插入一些数据。在运行这些代码后,可试着将COFFEES表和SUPPLIERS表关联起来查询(如第五个代码例子所示)。第六个代码例子是一个演示事务处理的应用程序,它也展示了如何使用for循环设置PreparedStatement对象中的占位符参数。
因为它们是完整的应用程序,所以代码中包括了一些前面代码段中没有看到的Java程序设计语言元素。在这里简要解释一下这些元素。
将代码放入类定义
在Java程序设计语言中,想要执行的代码都要放在类定义中。您要将类定义输入一个文件,然后将文件取名为类的名称,并在文件名后加上扩展名.java。因此如果类名是MySQLStatement,它的类定义应该放在名为MySQLStatement.java的文件中。
导入类使它们可见
首先是导引入新类中将要用到的包或类。我们例子中的类都使用java.sql包(JDBC API),在类定义前放入如下代码就可使用这个包:
import java.sql.*;
星号(*)指出要导入java.sql包中的所有类。导入类使它可见了,这表明使用该类中的方法或字段时不必写出完全限定名称。如果代码中没有包括“import java.sql.*;”,那么每次使用JDBC字段或方法时就要在它们前面写上“java.sql.”及类名。可以有选择地导入个别类而不是整个包。Java并不要求导入类或包,但这样做使代码编写要方便得多。
导入类的代码行出现在所有代码例子的顶部,因为要使导入的类对于所定义的类可见就必须这样做。实际类定义在导入类的代码行下面。
使用main方法
类要执行就要包含一个static public main方法。该方法就在声明类的代码行后面,它调用类中的其他方法。关键字static指出该方法操作在类级别上而不是操作在类的个别实例上。关键字public表明任何类的成员可以访问该方法。由于我们不只是要定义让其他类使用的类,而是要运行的类,所以本章的示例程序都包括一个main方法。
使用try和catch块
所有示例程序都包含的其他部分就是try和catch块。这是Java程序设计语言处理异常的机制。Java要求在方法抛出异常时有某种机制来处理它。一般catch块可捕获异常并指定处理办法(可选择不处理)。在示例代码中使用了两个try块和两个catch块。第一个try块包含了java.lang包中的Class.forName方法。这个方法抛出ClassNotFoundException异常,因此其后的catch块就处理那个异常。第二个try块包含了JDBC方法,这些方法都抛出SQLExceptions异常,因此在程序结束处有一个catch块处理可能抛出的其他所有异常,因为它们都是SQLException对象。
检索异常
JDBC允许查看DBMS和Java编译器生成的警告和异常。为看到异常可用catch块输出它们。例如,示例代码中的如下两个catch块输出解释异常的消息:
try {
// Code that could generate an exception goes here.
// If an exception is generated, the catch block below
// will print out information about it.
} catch(SQLException ex) {
System.err.println("SQLException: " + ex.getMessage());
}
try {
Class.forName("myDriverClassName");
} catch(java.lang.ClassNotFoundException e) {
System.err.print("ClassNotFoundException: ");
System.err.println(e.getMessage());
}
如果两次运行CreateCOFFEES.java将得到如下错误消息:
SQLException: There is already an object named 'COFFEES'
in the database.
Severity 16, State 1, Line 1
本例演示如何输出SQLException对象的消息部件,在多数场合这足以说明错误。
但该对象实际上有3个部件,为全面了解错误原因可将其全部输出。下面的代码段展示了以两种方式完成的catch块。首先是输出SQLException对象的所有3个部件:消息(一个描述错误的字符串)、SQL状态(根据X/Open SQLState规则指出错误的字符串)和供应商错误代码(指出驱动程序供应商错误代码的数字)。捕获了SQLException对象ex之后,就可通过方法getMessage、getSQLState和getErrorCode来访问它的3个部件。
完成下面代码段的第二种方式是取得所有已经抛出的异常。如果有第二个异常,它将与ex相连,可调用ex.getNextException查看是否有下一个异常。如果有,while循环将继续,并输出下一个异常的消息、SQLState和供应商错误代码。这个过程一直持续到没有异常为止。
try {
// Code that could generate an exception goes here.
// If an exception is generated, the catch block below
// will print out information about it.
} catch(SQLException ex) {
System.out.println("\n--- SQLException caught ---\n");
while (ex != null) {
System.out.println("Message: "
+ ex.getMessage ());
System.out.println("SQLState: "
+ ex.getSQLState ());
System.out.println("ErrorCode: "
+ ex.getErrorCode ());
ex = ex.getNextException();
System.out.println("");
}
}
如果将上面的catch块代入CreateCoffees.java中,那么在创建COFFEES表后运行会得到如下输出:
--- SQLException caught ---
Message: There is already an object named 'COFFEES' in the database.
Severity 16, State 1, Line 1
SQLState: 42501
ErrorCode: 2714
SQLState是X/Open和ANSI-92中定义的一个用于指出异常的代码。下面是SQLState代码编号及其含义的两个例子:
08001 -- No suitable driver
HY011 -- Operation invalid at this time
每个驱动程序的供应商错误代码都不一样,因此要得到错误代码及其含义的列表需要检查驱动程序文档。
检索警告
SQLWarning对象是SQLException的子类,用于处理数据库访问警告。就像异常一样,警告并不终止程序的执行;它们只是提醒用户——发生了一些未预料的事情。例如,一个警告可告诉您试图收回的特权并没有收回。或者一个警告可告诉您请求断开连接时发生了错误。
Connection对象、Statement对象(包括PreparedStatement和CallableStatement对象)或ResultSet对象都会报告警告。这些类都有getWarnings方法,为查看调用对象报告的第一个警告就必须调用该方法。如果getWarnings返回一个警告,就可在其上调用SQLWarning方法getNextWarning取得其他警告。自动执行一条语句会清除前一条语句的警告,因此警告不会迭加。但这也表明提取一条语句报告的警告必须在执行下一语句之前进行。
下面的代码段演示了如何获取Statement对象stmt及ResultSet对象rs上报告的警告的完整信息:
Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery("select COF_NAME from COFFEES");
while (rs.next()) {
String coffeeName = rs.getString("COF_NAME");
System.out.println("Coffees available at the Coffee Break: ");
System.out.println(" " + coffeeName);
SQLWarning warning = stmt.getWarnings();
if (warning != null) {
System.out.println("\n---Warning---\n");
while (warning != null) {
System.out.println("Message: "
+ warning.getMessage());
System.out.println("SQLState: "
+ warning.getSQLState());
System.out.print("Vendor error code: ");
System.out.println(warning.getErrorCode());
System.out.println("");
warning = warning.getNextWarning();
}
}
SQLWarning warn = rs.getWarnings();
if (warn != null) {
System.out.println("\n---Warning---\n");
while (warn != null) {
System.out.println("Message: "
+ warn.getMessage());
System.out.println("SQLState: "
+ warn.getSQLState());
System.out.print("Vendor error code: ");
System.out.println(warn.getErrorCode());
System.out.println("");
warn = warn.getNextWarning();
}
}
}
实际上警告很不常见。在报告的警告中,最常见的警告是DataTruncation警告——SQLWarning的一个子类。所有DataTruncation对象的SQLState都是01004,表示读写数据时出了问题。DataTruncation方法可用于查找截断了哪些列或参数的数据、是否在读/写操作上发生了截断,应传输字节数以及实际传输字节数。 |