JDBC - 异常处理



异常处理允许您以受控的方式处理异常情况,例如程序定义的错误。

当发生异常情况时,会抛出异常。“抛出”表示当前程序执行停止,控制权重定向到最近适用的 catch 子句。如果不存在适用的 catch 子句,则程序执行结束。

JDBC 异常处理与 Java 异常处理非常相似,但对于 JDBC,您将处理的最常见异常是java.sql.SQLException。

SQLException 方法

SQLException 既可能发生在驱动程序中,也可能发生在数据库中。当发生此类异常时,类型为 SQLException 的对象将传递到 catch 子句。

传递的 SQLException 对象具有以下可用于检索有关异常的附加信息的方法:

方法 描述
getErrorCode( ) 获取与异常关联的错误号。
getMessage( ) 获取 JDBC 驱动程序的错误消息(由驱动程序处理的错误),或获取数据库错误的 Oracle 错误号和消息。
getSQLState( ) 获取 XOPEN SQLstate 字符串。对于 JDBC 驱动程序错误,此方法不会返回任何有用的信息。对于数据库错误,将返回五位数的 XOPEN SQLstate 代码。此方法可能返回 null。
getNextException( ) 获取异常链中的下一个 Exception 对象。
printStackTrace( ) 将当前异常或可抛出对象及其回溯打印到标准错误流。
printStackTrace(PrintStream s) 将此可抛出对象及其回溯打印到您指定的打印流。
printStackTrace(PrintWriter w) 将此可抛出对象及其回溯打印到您指定的打印写入器。

通过利用从 Exception 对象中获得的信息,您可以捕获异常并适当地继续您的程序。以下是 try 块的一般形式:

try {
   // Your risky code goes between these curly braces!!!
}
catch(Exception ex) {
   // Your exception handling code goes between these 
   // curly braces, similar to the exception clause 
   // in a PL/SQL block.
}
finally {
   // Your must-always-be-executed code goes between these 
   // curly braces. Like closing database connection.
}

在 JDBC 示例中使用 try catch 块

学习下面的示例代码以了解try....catch 块的用法。在此示例中,我们有四个静态字符串用于数据库连接字符串、用户名、密码和一个调用存储过程的 SQL 查询。在 main 方法中,我们使用 DriverManager.getConnection() 方法准备与数据库的连接。我们使用 connection.prepareCall() 方法准备了一个 CallableStatement。下一步,设置占位符值并注册输出参数。最后,使用 CallableStatement.execute() 方法调用存储过程,并使用 getString() 方法检索员工姓名。在 catch() 语句中,我们处理 SQL 异常。由于使用了 try-with-resources,因此不需要 finally 语句,连接对象在 try-catch 语句完成后会自动关闭。

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class JDBCExample {
   static final String DB_URL = "jdbc:mysql://127.0.0.1/TUTORIALSPOINT";
   static final String USER = "guest";
   static final String PASS = "guest123";
   static final String QUERY = "{call getEmpName (?, ?)}";

   public static void main(String[] args) {
      // Open a connection
      try(Connection conn = DriverManager.getConnection(DB_URL, USER, PASS);
         CallableStatement stmt = conn.prepareCall(QUERY);
      ) {		      
         // Bind values into the parameters.
         stmt.setInt(1, 1);  // This would set ID
         // Because second parameter is OUT so register it
         stmt.registerOutParameter(2, java.sql.Types.VARCHAR);
         //Use execute method to run stored procedure.
         System.out.println("Executing stored procedure..." );
         stmt.execute();
         //Retrieve employee name with getXXX method
         String empName = stmt.getString(2);
         System.out.println("Emp Name with ID: 1 is " + empName);
      } catch (SQLException e) {
         e.printStackTrace();
      } 
   }
}

现在,让我们按如下方式编译上述示例:

C:\>javac JDBCExample.java
C:\>

如果您运行JDBCExample,如果没有任何问题,它将产生以下结果;否则,将捕获相应的错误并显示错误消息:

C:\>java JDBCExample
Executing stored procedure...
Emp Name with ID: 1 is Zara
C:\>

尝试通过传递错误的数据库名称或错误的用户名或密码来运行上述示例,并检查结果。

针对无效表名处理 SQLException 并使用 JDBC 示例中的错误代码

在此示例中,我们有三个静态字符串用于数据库连接字符串、用户名、密码。在 main 方法中,我们使用 DriverManager.getConnection() 方法准备与数据库的连接。我们使用 connection.createStatement() 方法准备了一个 Statement。使用 statement.executeQuery() 执行带有无效表名的查询,这将导致 SQLException。异常在 catch 块中处理,并打印错误代码、SQL 状态和详细的错误消息。

import java.sql.*; 
 
public class JDBCExceptionExample {
    static final String MYSQL_URL = "jdbc:mysql://127.0.0.1/TUTORIALSPOINT";
    static final String USER_NAME = "guest";
    static final String PASSWORD = "guest123";
    
    public static void main(String args[]) {
        try{            
            Connection conn = DriverManager.getConnection(MYSQL_URL, USER_NAME, PASSWORD);
            
            Statement stmt = conn.createStatement();
            // Giving incorrect table name to get Exceptions
            ResultSet rs = stmt.executeQuery("SELECT * FROM EMPLOYEES10");
            
            while( rs.next()){
                System.out.println("ID:" + rs.getInt("id"));
                System.out.println(", Age: " + rs.getInt("age"));
            }
            
        }catch(SQLException e){
            int errorCode = e.getErrorCode();
            String sqlState = e.getSQLState();
            String errorMsg = e.getMessage();
            
            System.out.println("Error code: " + errorCode);
            System.out.println("SqlState: " + sqlState);
            System.out.println("Error Message: " + errorMsg);
            
            e.printStackTrace();
        }
    }
}

输出

现在,让我们按如下方式编译上述示例:

C:\>javac JDBCExceptionExample.java
C:\>

运行JDBCExceptionExample时,它会产生以下结果:

C:\>java JDBCExceptionExample
Error code: 1146
SqlState: 42S02
Error Message: Table 'tutorialspoint.employees10' doesn't exist
java.sql.SQLSyntaxErrorException: Table 'tutorialspoint.employees10' doesn't exist
	at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:112)
	at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:113)
	at com.mysql.cj.jdbc.StatementImpl.executeQuery(StatementImpl.java:1286)
	at JDBCExceptionExample.main(JDBCExceptionExample.java:26)
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
	at java.base/java.lang.reflect.Method.invoke(Method.java:580)
	at jdk.compiler/com.sun.tools.javac.launcher.Main.execute(Main.java:484)
	at jdk.compiler/com.sun.tools.javac.launcher.Main.run(Main.java:208)
	at jdk.compiler/com.sun.tools.javac.launcher.Main.main(Main.java:135)

C:\>

针对无效列名处理 SQLException 并使用 JDBC 示例中的错误代码

在此示例中,我们有三个静态字符串用于数据库连接字符串、用户名、密码。在 main 方法中,我们使用 DriverManager.getConnection() 方法准备与数据库的连接。我们使用 connection.createStatement() 方法准备了一个 Statement。使用 statement.executeQuery() 执行带有无效列名的查询,这将导致 SQLException。异常在 catch 块中处理,并打印错误代码、SQL 状态和详细的错误消息。

import java.sql.*;

public class JDBCExceptionExample {
    
    static final String MYSQL_URL = "jdbc:mysql://127.0.0.1/TUTORIALSPOINT";
    static final String USER_NAME = "guest";
    static final String PASSWORD = "guest123";
    
    public static void main(String args[]) {
        try{
            Connection conn = DriverManager.getConnection( MYSQL_URL, USER_NAME, PASSWORD);
            System.out.println("Connection to db established..");
            String query = "select * from employees";
            Statement stmt = conn.createStatement();
            ResultSet rs = stmt.executeQuery(query);
            System.out.println("Successfully executed query.");
            while(rs.next()){
                System.out.println("Intentionally giving emp_id column name, when the correct "
                        + "one is: id. Giving this, to see exception handling.");
                System.out.println("ID: " + rs.getString("emp_id"));
            }
        }catch(SQLException e){
            Throwable t = e.getCause();
            System.out.println("Exception caught. Cause: " + t.toString());
            System.out.println("------------------------------------");
            e.printStackTrace();
        }
    }
}

输出

现在,让我们按如下方式编译上述示例:

C:\>javac JDBCExceptionExample.java
C:\>

运行JDBCExceptionExample时,它会产生以下结果:

C:\>java JDBCExceptionExample
Connection to db established..
Successfully executed query.
Intentionally giving emp_id column name, when the correct one is: id. Giving this, to see exception handling.
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "java.lang.Throwable.toString()" because "" is null
	at JDBCExceptionExample.main(JDBCExceptionExample.java:55)

C:\>
广告