try{
Class.forName ("oracle.jdbc.driver.OracleDriver"); // identify
Connection con = DriverManager.getConnection
("jdbc:oracle...",userid,password);
// create Statement and execute sql statement after
} catch (SQLException ex) {
Logger.getLogger(Transcript.class.getName()).log(Level.SEVERE, null, ex);
}
我能找到的唯一例外是SQLException,但它如何区分登录失败和不正确的sql语句?
我希望它重新向用户承诺输入id和密码的另一个机会,我把它放在catch块中吗?
如果是这样,我是否需要另一个嵌套的try-catch来处理异常?
因为我想分别处理这两种情况,但似乎只有一个SQLException我可以使用。
答案 0 :(得分:1)
实际上,您还会得到更多:
If you don't have the right Oracle driver in the classpath in Class.forName:
Exception in thread "main" java.lang.ClassNotFoundException: oracle.jdbc.driver.OracleDriver
If DriverManager.getConnection fails because of a wrong jdbc url syntax:
Exception in thread "main" java.sql.SQLException: No suitable driver found for jdbc:oracle...
If login/password fails at DriverManager.getConnection
Exception in thread "main" java.sql.SQLException: ORA-01017: invalid username/password; logon denied
In case of an incorrect SQL statement:
Exception in thread "main" java.sql.SQLSyntaxErrorException: ORA-00942: table or view does not exist
In case of an incorrect SQL statement:
Exception in thread "main" java.sql.SQLSyntaxErrorException: ORA-00900: invalid SQL statement
In case of an incorrect SQL statement:
Exception in thread "main" java.sql.SQLException: Invalid column name
您可以将登录失败与SQL失败分开,因为它们发生在代码中的不同位置。
public class Oracle {
public static void main(final String[] args) throws ClassNotFoundException, SQLException {
final Connection con;
try {
Class.forName ("oracle.jdbc.driver.OracleDriver");
} catch (final Exception e) {
throw new RuntimeException("Driver failure");
}
try {
con = DriverManager.getConnection ("jdbc:oracle:thin:schema/password@host:port:sid");
} catch (final Exception e) {
throw new RuntimeException("Login failure");
}
try {
final Statement stmt = con.createStatement();
final String sql = "select 1 from dual";
final ResultSet rs = stmt.executeQuery(sql);
while(rs.next()) {
// do something with the data
}
rs.close();
} catch (final Exception e) {
throw new RuntimeException("SQL failure");
}
}
}
注意:这是一个暴力示例,在生产代码中您可能需要更精确的异常处理程序,并且您应确保资源始终关闭。例如,如果在读取resut集时发生SQL错误并因为引用无效列而出错,则可能需要关闭语句以及结果集。
另外两个特定于Oracle的提示:
不要将登录名和密码作为参数传递给DriverManager.getConnection。 Oracle连接有更多参数,构建包含所有内容的JDBC URL更容易:" jdbc:oracle:thin:schema / password @ host:port:sid"
在真正的Oracle异常的情况下,异常被包装到SQLException或SQLSyntaxErrorException,有时这个,有时是。我发现将自己的逻辑置于此之上非常方便:
我通过try..catch捕获任何异常。如果错误消息以ORA-开头,则表示Oracle错误,我将其包装到自定义异常类并重新抛出。
在自定义异常中解析Oracle错误代码可能很方便。您可以使用它来区分您在PL / SQL中抛出的自定义Oracle异常(-20000 ..- 20999)(并且可以指示业务级错误)。其余的错误代码总是会出现技术错误,即代码或数据库结构中出现错误。
要关闭资源(java7之前版本),请使用try..finally。请注意,在实际关闭资源时对可能的进一步异常的悲观处理失败。
Statement stmt=null;
ResultSet rs=null;
try {
try {
final Statement stmt = con.createStatement();
final String sql = "select 1 from dual";
rs = stmt.executeQuery(sql);
while(rs.next()) {
// do something with the data
}
rs.close();
rs=null;
stmt.close();
stmt=null;
} catch (final Exception e) {
throw new RuntimeException("SQL failure");
}
} finally {
if (rs!=null) {
try {
rs.close();
} catch (Exception e) {
// ignore - we can't do too much
}
}
if (stmt!=null) {
try {
stmt.close();
} catch (Exception e) {
// ignore - we can't do too much
}
}
}
要关闭Java7及更高版本的资源,您可以从尝试使用资源块中受益。见How should I use try-with-resources with JDBC?