从Java ResultSet检查null int值

ian*_*cho 266 java null resultset

在Java中,我试图从ResultSet中测试一个空值,其中列被转换为原始int类型.

int iVal;
ResultSet rs = magicallyAppearingStmt.executeQuery(query);
if (rs.next()) {
  if (rs.getObject("ID_PARENT") != null && !rs.wasNull()) {
    iVal = rs.getInt("ID_PARENT");
  }
}
Run Code Online (Sandbox Code Playgroud)

从上面的代码片段,有更好的方法来做到这一点,我假设第二个isNull()测试是多余的?

教育我们,谢谢

Ric*_*ard 349

ResultSet.getInt字段值的默认值是NULL返回0,这也是iVal声明的默认值.在这种情况下,您的测试完全是多余的.

如果你真的想要做一些不同的事情,如果字段值是NULL,我建议:

int iVal = 0;
ResultSet rs = magicallyAppearingStmt.executeQuery(query);
if (rs.next()) {
    iVal = rs.getInt("ID_PARENT");
    if (rs.wasNull()) {
        // handle NULL field value
    }
}
Run Code Online (Sandbox Code Playgroud)

(编辑为@martin评论如下;编写的OP代码无法编译,因为iVal未初始化)

  • 事实上,事实是荒谬的.`getInt()`应该是`getInteger()`,如果DB值是'null`,它返回一个`null`,它是`null`.开发人员真的搞砸了这个. (141认同)
  • OMG为什么,只是不返回NULL,`0`和`NULL`是两个很大的不同的东西 (8认同)
  • @sactiw遵循这个逻辑,java上的所有内容都应该被开发以避免NPE,但事实并非如此.避免NPE是应用程序开发人员的责任,而不是语言内部API. (7认同)
  • @Roman - 在ResultSet中查看getInt的javadoc:"返回:列值;如果值为SQL NULL,则返回的值为0" (5认同)
  • 我刚刚在docs中找到了相同的声明.它值得在SO imho上单独一个帖子.(http://java.sun.com/j2se/1.4.2/docs/api/java/sql/ResultSet.html#getObject(int)) (2认同)
  • 仅供记录:我不认为`iVal`的默认值为0(至少不在此片段中).在"NULL"列的情况下,"iVal"刚刚未初始化并且访问它将产生编译器错误. (2认同)
  • 从同一个结果集进行并发读取时,“wasNull()”会出现问题。不要沉迷于过去;) (2认同)
  • @sactiw 如果返回参数是可为空的对象(“Integer”),则不会拆箱。开发人员错了,因为“null”和“0”不是同一值。因此,当值为“null”时返回“0”是不正确的(并且对于编写生产代码的 API 新手来说确实很混乱)。 (2认同)
  • @ryvantage ResultSet是原始的Java类之一,可以追溯到Java不支持自动拆箱的时候。同样,它是一个非常低级的API,它不应强制将来自Java Integer对象中的数据库的原始字节包装起来的潜在额外成本。可能存在一个参数,用于将getInteger添加到返回Integer的接口(甚至是Optional <Integer>)。 (2认同)
  • @sactiw我知道任何可为空的对象都有NPE的风险,但是API方法本身不会抛出NPE的风险。您反对`getInteger()`的论点是反对`null`作为构造的一般论点。但是,只要Java中存在“ null”并且只要数据库值为“ null”,那么该方法就应该返回。不可争辩:当值为null时返回“ 0”是不正确的。 (2认同)

小智 81

另一种方案:

public class DaoTools {
    static public Integer getInteger(ResultSet rs, String strColName) throws SQLException {
        int nValue = rs.getInt(strColName);
        return rs.wasNull() ? null : nValue;
    }
}
Run Code Online (Sandbox Code Playgroud)


And*_*s_D 28

我认为,这是多余的.rs.getObject("ID_PARENT")应返回一个Integer对象,或者null,如果列值实际是NULL.所以甚至应该可以这样做:

if (rs.next()) {
  Integer idParent = (Integer) rs.getObject("ID_PARENT");
  if (idParent != null) {
    iVal = idParent; // works for Java 1.5+
  } else {
    // handle this case
  }      
}
Run Code Online (Sandbox Code Playgroud)

  • 嗯,至少在我的情况下,问题是调用`getObject`不一定返回一个Integer,因为我正在使用的oracle db中的列类型的性质("Number"). (5认同)
  • 也可以做`rs.getObject("ID_PARENT", Integer.class)` (3认同)

Bal*_*usC 25

只需检查该字段是否null使用ResultSet#getObject().-1用你想要的任何null-case值替换.

int foo = resultSet.getObject("foo") != null ? resultSet.getInt("foo") : -1;
Run Code Online (Sandbox Code Playgroud)

或者,如果您可以保证使用正确的DB列类型,以便ResultSet#getObject()真正返回Integer(因此不是Long,ShortByte),那么您也可以将它强制转换为Integer.

Integer foo = (Integer) resultSet.getObject("foo");
Run Code Online (Sandbox Code Playgroud)

  • 不,但它会在非空情况下构造一个不必要的 Integer 对象。(顺便说一句,大多数 JDBC 驱动程序在任何 ResultSet 方法调用期间根本不会命中数据库……通常,在所有数据都通过网络传输之前,您不会得到 ResultSet )。 (2认同)

Pet*_*ans 11

你可以简单地使用AFAIK

iVal = rs.getInt("ID_PARENT");
if (rs.wasNull()) {
  // do somthing interesting to handle this situation
}
Run Code Online (Sandbox Code Playgroud)

即使它是NULL.


小智 6

只是 Java 泛型的更新。

您可以创建一个实用程序方法来从给定的 ResultSet 中检索任何 Java 类型的可选值,之前已进行转换。

不幸的是,getObject(columnName, Class) 不返回 null,而是给定 Java 类型的默认值,因此需要 2 次调用

public <T> T getOptionalValue(final ResultSet rs, final String columnName, final Class<T> clazz) throws SQLException {
    final T value = rs.getObject(columnName, clazz);
    return rs.wasNull() ? null : value;
}
Run Code Online (Sandbox Code Playgroud)

在此示例中,您的代码可能如下所示:

final Integer columnValue = getOptionalValue(rs, Integer.class);
if (columnValue == null) {
    //null handling
} else {
    //use int value of columnValue with autoboxing
}
Run Code Online (Sandbox Code Playgroud)

很高兴得到反馈