当“获取”错误类型的数据时,为什么ResultSet中的get不会引发异常?

问题描述

我有2列的表cities一个ID整数主键),另一个NAME文本不为空)。 当我做类似的事情时:

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吗?为什么会这样呢?以及如何将主键转换为String(当我没有进行任何显式转换时)?

解决方法

ResultSet javadoc中所述:

对于getter方法,JDBC驱动程序尝试将 底层数据为getter方法中指定的Java类型,并且 返回合适的Java值。 JDBC规范有一个表 显示允许的从SQL类型到Java类型的映射 由ResultSet getter方法使用。

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

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

还允许在字符串类型的列(例如getInt(..))上使用VARCHAR,但存在更多限制:该值必须可解析为int。您显示的示例似乎来自不兼容的驱动程序,该驱动程序将不可解析的值转换为0而不抛出异常。

关于此,JDBC 1.20规范说:

如果您尝试非法转换,或者数据转换失败 (例如,如果您对SQL VARCHAR值“ foo”执行了getInt), 那么将引发SQLException。

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

,

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

大多数getString()方法用于获取CHAR和VARCHAR SQL类型,但可用于获取任何SQL类型,但也有其局限性。 如果使用它来检索数字类型,则getString()会将数字值转换为java String对象,为了使用该值,必须先将其转换回数字类型,然后才能将其用作数字类型。