SMALLINT 返回 Integer
pgJDBC 把 SMALLINT 的默认 getObject 结果映射为 Integer,元数据类名也因此是 Integer。需要 Short 时采用显式类型读取,并保留 SQL NULL。
PostgreSQL 的列是 SMALLINT,pgJDBC 的 getColumnType() 也返回 Types.SMALLINT,但 getColumnClassName() 却是 java.lang.Integer。应用若据此认为驱动读错了类型,或把普通 getObject() 的结果强转为 Short,容易走错处理方向。
pgJDBC 42.7.14 的这一表现符合 JDBC 的默认对象映射。SQL 类型对应的原始 Java 数值类型,与 getObject() 返回的包装类不是完全相同的映射:SMALLINT 的默认对象是 Integer。
元数据描述的是默认读取结果
pgJDBC 的类型表把 PostgreSQL int2 记为 Types.SMALLINT,对应 Java 类为 Integer。普通 getObject() 对这一类型走的是 getInt() 分支,所以元数据与实际返回对象相符。
这不表示数据库把列扩成了 INTEGER,也不要求修改表结构。先核对 SQL 类型、Java 类名和实际采用的读取方法;不要仅凭包装类名称不同,就把这个行为当作 42.7.14 的回归。
通用结果映射器若需要保持 JDBC 默认约定,就接受这里的 Integer。若业务字段明确要求 Short,应选择显式的类型读取,而不是把默认对象直接强转。
显式读取 Short
已核对的 pgJDBC 42.7.14 支持对 SMALLINT 调用 getObject(column, Short.class),并为 SQL NULL 返回 null。下面使用应用已有的 connection 做只读示例查询;需要导入 java.sql.Statement 与 java.sql.ResultSet:
try (Statement st = connection.createStatement();
ResultSet rs = st.executeQuery(
"SELECT 123::smallint AS v UNION ALL SELECT NULL::smallint")) {
while (rs.next()) {
Short value = rs.getObject(1, Short.class);
System.out.println(value);
}
}
示例只查询固定值,不改现有表。连接仍应采用应用原有的认证、TLS 和权限配置;不要为排查另外开放数据库入口。
也可以用 getShort(),但它返回原始 short,SQL NULL 会得到 0。需要保留空值时,在这次读取后立即检查 wasNull(),中间不要读取其他列后再检查。
不要把这个处理扩展成“所有 Number 都调用 shortValue()”。对于更宽的整数或其他数值类型,缩窄转换可能丢失范围和精度。通用映射器应先按实际 JDBC 类型选择读取方法,再满足目标字段的范围和空值约定。
验收映射器,不必修改数据
覆盖业务使用的非空值、边界值和 SQL NULL。确认目标字段收到预期包装类,空值没有变成零,DTO、序列化和后续计算仍保持原约定。
如果 ORM 或结果映射层已经做了转换,还需核对它交给业务代码的对象,不能只看底层 ResultSet。需要撤回时恢复映射器与配套字段定义;这项调整不需要批量修改数据库中的值。
升级驱动可以包含其他维护修正,但不会把符合默认约定的 SMALLINT 对象映射自动改成 Short。将读取契约写清楚,比反复更换驱动版本更有针对性。


