为什么在ResultSet中调用get()获取错误类型的数据时不会抛出异常?

huangapple go评论79阅读模式
英文:

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

问题

有趣的是,当我将打印语句更改为以下内容时,程序并没有崩溃。请注意,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 吗?为什么会出现这种结果?还有,它是如何将主键转换为字符串的(当我没有进行任何显式转换时)?

英文:

Say I have table cities with 2 columns. One is ID (integer primary key), other is NAME (text not null).
When I do something like:

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

I get nice result of:

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

But! Watch what happens when I change print statement to this. Notice how get() methods have incorrect data type from actual data in database.

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

What surprised me is that program didn't crash. Instead it got:

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

Why is it designed this way? Shouldn't I get some sort of castException? And why this result? Also how it can convert primary key to String (when I didn't do any explicit casting)?

答案1

得分: 2

正如在 ResultSet 的 javadoc 中所记录:

> 对于 getter 方法,JDBC 驱动程序会尝试将底层数据转换为 getter 方法中指定的 Java 类型,并返回适当的 Java 值。JDBC 规范中有一张表显示了从 SQL 类型到可以被 ResultSet getter 方法使用的 Java 类型的允许映射。

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

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

在字符串类型列(例如 VARCHAR)上使用 getInt(..) 也是允许的,但具有更多的限制:值必须能够解析为一个 int。您展示的示例似乎来自一个不符合规范的驱动程序,它将无法解析的值转换为 0,而不是抛出异常。

在此情况下,JDBC 1.20 规范说道:

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

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

英文:

As documented in the 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.

So, being able to perform a getString(..) on an integer column is perfectly acceptable, and the driver will do the conversion for you (eg using String.valueOf(int) or something similar).

The JDBC 4.3 specification, appendix B, contains tables of mappings that the JDBC specification expects drivers to support, but be aware that some drivers might support more conversions than listed (and - unfortunately - some do not support all conversions listed).

The use of getInt(..) on a string-type column (eg VARCHAR) is also allowed, but comes with more limitations: the value must be parseable to an int. The example you show seems to be from a non-compliant driver that converts non-parseable values to 0 instead of throwing an exception.

On this, the JDBC 1.20 specification says:

> 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.

Although this is no longer explicitly mentioned in recent JDBC specifications, it is still expected behaviour. You should report a bug to the maintainer of your JDBC driver on this.

答案2

得分: -1

JDBC规范中有一张表格,显示了在ResultSet获取器方法中允许的SQL类型到Java类型的所有映射。

通常使用getString()方法来获取SQL类型CHAR和VARCHAR,但它也可以用来获取任何SQL类型,但它也有其局限性。
如果你用它来检索数值类型,那么getString()会将数值转换为Java String对象,为了使用该值,必须在将其视为数值类型之前将其转换回数值类型。

英文:

The JDBC specification has a table which shows which all mapping of SQL types to Java types that are allowed in ResultSet getter method.

Mostly getString() method is used to get SQL types CHAR and VARCHAR but it can be used to fetch any SQL type but it also has its limitation.
If you used it to retrieve a numeric type, then getString() converts numeric value to java String object, and in order to use that value it has to be converted back to numeric type before it can be operated as numeric type.

huangapple
  • 本文由 发表于 2020年9月26日 13:15:51
  • 转载请务必保留本文链接:https://go.coder-hub.com/64074148.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定