这些Java教程是为JDK 8编写的。本页中描述的示例和实践不利用后续版本中引入的改进,并可能使用不再可用的技术。
有关Java SE 9及其后续版本中更新的语言功能的概述,请参阅Java语言更改。
有关所有JDK版本的新功能、增强功能以及已删除或弃用选项的信息,请参阅JDK发行说明。
本页面涵盖以下主题:
当JDBC在与数据源交互过程中遇到错误时,会抛出SQLException
的实例,而不是Exception
。(在此上下文中,数据源代表Connection
对象连接的数据库。)SQLException
实例包含以下信息,可以帮助您确定错误的原因:
错误的描述。通过调用方法SQLException.getMessage
来检索包含此描述的String
对象。
SQLState代码。这些代码及其相应的含义已经由ISO/ANSI和Open Group(X/Open)标准化,尽管一些代码已保留供数据库供应商自行定义。此String
对象由五个字母数字字符组成。通过调用方法SQLException.getSQLState
来检索此代码。
错误代码。这是一个整数值,用于标识导致抛出SQLException
实例的错误。其值和含义是特定于实现的,并且可能是底层数据源返回的实际错误代码。通过调用方法SQLException.getErrorCode
来检索错误。
原因。一个SQLException
实例可能有一个因果关系,它由一个或多个导致SQLException
实例被抛出的Throwable
对象组成。要浏览这个因果关系链,递归调用方法SQLException.getCause
,直到返回null
值为止。
对任何链接异常的引用。如果发生多个错误,则通过此链引用异常。通过在抛出的异常上调用方法SQLException.getNextException
来检索这些异常。
以下方法,JDBCTutorialUtilities.printSQLException
,输出SQLException
中包含的SQLState、错误代码、错误描述和原因(如果有)以及与之链接的任何其他异常:
public static void printSQLException(SQLException ex) { for (Throwable e : ex) { if (e instanceof SQLException) { if (ignoreSQLException( ((SQLException)e). getSQLState()) == false) { e.printStackTrace(System.err); System.err.println("SQL状态: " + ((SQLException)e).getSQLState()); System.err.println("错误代码: " + ((SQLException)e).getErrorCode()); System.err.println("消息: " + e.getMessage()); Throwable t = ex.getCause(); while(t != null) { System.out.println("原因: " + t); t = t.getCause(); } } } } }
例如,如果你使用Java DB作为你的数据库管理系统,并调用CoffeesTable.dropTable
方法,而表COFFEES
不存在,并且你移除了对JDBCTutorialUtilities.ignoreSQLException
方法的调用,输出结果将类似于以下内容:
SQL状态: 42Y55 错误代码: 30000 消息: 因为它不存在,无法执行“DROP TABLE”操作于“TESTDB.COFFEES”。
你可以不打印SQLException
信息,而是首先检索SQLState
,然后根据SQLException
进行处理。例如,如果SQLState
等于代码42Y55
(并且你使用Java DB作为你的数据库管理系统),JDBCTutorialUtilities.ignoreSQLException
方法返回true
,这将导致JDBCTutorialUtilities.printSQLException
忽略这个SQLException
:
public static boolean ignoreSQLException(String sqlState) { if (sqlState == null) { System.out.println("未定义SQL状态!"); return false; } // X0Y32: 架构中已经存在JAR文件 if (sqlState.equalsIgnoreCase("X0Y32")) return true; // 42Y55: 架构中已经存在表 if (sqlState.equalsIgnoreCase("42Y55")) return true; return false; }
SQLWarning
对象是SQLException
的子类,用于处理数据库访问的警告信息。警告不会像异常一样停止应用程序的执行,它们只是提醒用户某些计划中的事情没有按计划发生。例如,警告可能告诉你你尝试撤销的权限没有被撤销。或者警告可能告诉你在请求的断开连接期间发生了错误。
警告可以在Connection
对象、Statement
对象(包括PreparedStatement
和CallableStatement
对象)或ResultSet
对象上报告。每个这些类都有一个getWarnings
方法,你必须调用它才能看到在调用对象上报告的第一个警告。如果getWarnings
返回一个警告,你可以调用SQLWarning
方法getNextWarning
来获取任何其他警告。执行语句会自动清除前一个语句的警告,所以它们不会积累。这意味着,如果你想要检索报告在一个语句上的警告,你必须在执行另一个语句之前这样做。
以下来自JDBCTutorialUtilities.java
中的方法演示了如何获取关于Statement
或ResultSet
对象报告的任何警告的完整信息:
public static void getWarningsFromResultSet(ResultSet rs) throws SQLException { JDBCTutorialUtilities.printWarnings(rs.getWarnings()); } public static void getWarningsFromStatement(Statement stmt) throws SQLException { JDBCTutorialUtilities.printWarnings(stmt.getWarnings()); } public static void printWarnings(SQLWarning warning) throws SQLException { if (warning != null) { System.out.println("\n---警告---\n"); while (warning != null) { System.out.println("消息: " + warning.getMessage()); System.out.println("SQL状态: " + warning.getSQLState()); System.out.print("供应商错误代码: "); System.out.println(warning.getErrorCode()); System.out.println(""); warning = warning.getNextWarning(); } }
最常见的警告是DataTruncation
警告,它是SQLWarning
的子类。所有的DataTruncation
对象都有一个SQL状态码01004
,表示读取或写入数据时发生了问题。DataTruncation
方法可以让您查找数据在哪个列或参数中被截断,截断是读取操作还是写入操作,应该传输多少字节以及实际传输了多少字节。
您的JDBC驱动程序可能会抛出SQLException
的子类,对应于常见的SQL状态码或不与特定SQL状态码类值关联的常见错误状态码。这样可以编写更可移植的错误处理代码。这些异常是以下类的子类之一:
SQLNonTransientException
SQLTransientException
SQLRecoverableException
有关这些子类的更多信息,请参见java.sql
包的最新Javadoc或您的JDBC驱动程序的文档。
还可以抛出以下SQLException
的子类:
BatchUpdateException
。除了SQLException
提供的信息外,BatchUpdateException
还提供了在错误发生之前执行的所有语句的更新计数。SQLClientInfoException
。除了SQLException
提供的信息外,SQLClientInfoException
还提供了未设置的客户端信息属性的列表。