当 'getting' 错误的数据类型时,为什么 ResultSet 中的 get() 不抛出异常?

Why doesn't get() in ResultSet throw exception when 'getting' wrong type of data?

假设我有 table cities 两列。一个是ID整数主键),另一个是NAMEtext not null)。 当我做类似的事情时:

resultSet = statement.executeQuery("select * from cities");
while (resultSet.next()){
System.out.println("ID and Name: " + resultSet.getInt(1) + "," + resultSet.getString(2));
}

我得到了不错的结果:

ID and Name: 1,london
ID and Name: 2,madrid
ID and Name: 3,paris

但是!观察当我将打印语句更改为此时会发生什么。请注意 get() 方法 如何从数据库中的实际数据中获取不正确的数据类型。

System.out.println("ID and Name: " + resultSet.getString(1) + "," + resultSet.getInt(2));

令我惊讶的是程序没有崩溃。相反,它得到了:

ID and Name: 1,0
ID and Name: 2,0
ID and Name: 3,0

为什么这样设计?我不应该得到某种 castException 吗?为什么会出现这个结果?还有它如何将主键转换为字符串(当我没有进行任何显式转换时)?

JDBC 规范有一个 table,它显示 ResultSet getter 方法中允许的 SQL 类型到 Java 类型的所有映射。

getString() 方法主要用于获取 SQL 类型的 CHAR 和 VARCHAR,但它可以用于获取任何 SQL 类型,但它也有其局限性。 如果你用它来检索数字类型,那么 getString() 会将数字值转换为 java String 对象,并且为了使用该值必须将其转换回数字类型才能作为数字类型进行操作.

ResultSet javadoc 中所述:

For the getter methods, a JDBC driver attempts to convert the underlying data to the Java type specified in the getter method and returns a suitable Java value. The JDBC specification has a table showing the allowable mappings from SQL types to Java types that can be used by the ResultSet getter methods.

因此,能够对整数列执行 getString(..) 是完全可以接受的,驱动程序将为您进行转换(例如使用 String.valueOf(int) 或类似的东西)。

JDBC 4.3 specification,附录 B,包含 JDBC 规范期望驱动程序支持的映射表,但请注意,某些驱动程序可能支持比列出的更多的转换(并且 - 不幸的是 - 一些不支持列出的所有转换)。

也允许在 string-type 列(例如 VARCHAR)上使用 getInt(..),但有更多限制:该值必须可解析为 int.您显示的示例似乎来自 non-compliant 驱动程序,该驱动程序将 non-parseable 值转换为 0 而不是抛出异常。

对此,JDBC 1.20 规范说:

If you attempt an illegal conversion, or if a data conversion fails (for example if you did a getInt on a SQL VARCHAR value of “foo”), then a SQLException will be raised.

虽然在最近的 JDBC 规范中不再明确提及,但这仍然是预期的行为。您应该就此向 JDBC 驱动程序的维护者报告错误。