5

这不是我现在遇到的具体问题,只是我无法解决的问题。我在这里找不到任何问题或互联网上有关此的信息。

Java 中从一开始就存在包装类,例如java.lang.Integer(对于原语)。int但是JDBCgetInt的开发人员选择getLong使用 Java 原语来实现方法。原语的问题是它们不能代表 SQL NULL

为了解决这个问题,JDBC 开发人员编写了许多方法来返回默认的原始值,例如0false当列是时NULL,并引入了一个wasNull()函数供用户检查它是否应该是null。更糟糕的是,当许多其他方法(例如PreparedStatement 的 setInt接受原语而不是包装对象)时,用户必须有条件地使用setNull将相应列设置为NULL.

我发现这为其用户使用JDBC API 的方式增加了不必要的复杂性。如果 JDBC 的ResultSet对象在列有 SQL 时getInteger将 Javanull作为Integer 对象NULL返回,那将非常方便而无需检查wasNull。Java 的拆箱会自动处理必须将Integer对象分配给int原始变量的情况,将其转换为0. 如果PreparedStatement有一个setInteger方法,用户可以简单地使用它来为合适的列设置值 - 包括 SQLNULL值 - 而无需检查它是否应该为 null 并恢复为setNull.

即使到现在,也没有对 JDBC 进行任何更改来纠正此异常。即使我们已经在 J​​ava 1.7 或 1.8 中,JDBC 仍继续使用原始类型(对吗?)。Java 的内置装箱和拆箱将确保使用原始类型编写的旧应用程序将继续与更新为使用包装器的 JDBC 版本一起正常工作。那么,为什么没有人费心升级 JDBC 以使用包装对象代替原语呢?

PS:很高兴听到针对 JDBC 这个荒谬问题的推荐替代解决方案。

4

2 回答 2

5

尽管它不能完全回答您的问题,但 JDBC 1.2 规范包含以下“拒绝”设计选择

A.8 对 GetObject 与 getXXX的支持
由于各种 get/set 方法与通用 getObject/setObject 方法之间的重叠,我们考虑放弃我们的 get/set 方法并简单地使用 getObject/setObject。然而,对于程序员知道 SQL 类型的简单常见情况,生成的强制转换和提取非常乏味:
int i = ((Integer)r.getObject(1, java.sql.Types.INTEGER)).intValue()
因此,我们决定在这种情况下稍微改变我们的极简主义原则,并保留各种 get/set 方法作为大多数应用程序程序员,同时还为工具构建者和复杂应用程序添加 getObject/setObject 方法

该规范的第 14 章还说:

例如,SQL INTEGER 通常映射到 Java int。这支持一个简单的接口,用于将 SQL 值作为简单的 Java 类型进行读取和写入。

第 2 章说:

提供与 Java 系统其余部分一致的 Java 接口

据我所知,大多数 Java API 使用原始类型而不是包装类型。

同样在规范发布时(1.2 日期为 1997 年 1 月 10 日),没有装箱和拆箱,使用Integeretc 相当麻烦。例如,您根本无法Integer直接进行数学运算,您首先需要调用intValue()以获得 an int,然后才能实际执行任何基本操作,如加法、乘法等,然后您需要将结果转换回 anInteger以存储它。这听起来是为基元设置 getter 和 setter 的一个很好的理由。

请记住,该规范是在 1995 年到 1997 年之间设计的,在那个时代,内存相对昂贵,而用于基元的包装器对象只会消耗更多内存。我相信一个简单的对象是 8 个字节 + 原始字段的大小。对于一个int12 个字节而不是 4 个字节的成本。

于 2013-08-12T14:36:11.513 回答
3

一句话—​​—兼容性。JDBC API 早在自动装箱之前就已发布,现在更改它需要所有 3rd 方供应商更新和发布他们的 JDBC 实现 - 一个逻辑上的噩梦,如果它甚至可能的话,加上那些使用 JDBC API 的人将不得不适应行为的任何变化。

改变这种类型的明显方法是发布一个新的 API,如果你愿意的话,JDBC2,尽管恕我直言 JDBC 已经损坏到保证这一点,特别是考虑到 JPA/Hibernate 在最常见的用法中隐藏了低级 JDBC API .

于 2013-08-12T11:11:38.803 回答