在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");
  }
}

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

教育我们,谢谢


当前回答

只是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;
}

在这个例子中,你的代码如下所示:

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

乐于得到反馈

其他回答

使用java 8,你可以这样做:

Long nVal = Optional.ofNullable(resultSet.getBigDecimal("col_name"))
                    .map(BigDecimal::longValue).orElse(null));

在这种情况下,如果SQL值为null,则确保nVal将为null(而不是零)

为了方便,您可以为ResultSet创建一个包装器类,当ResultSet通常不会返回空值时,它会返回空值。

public final class ResultSetWrapper {

    private final ResultSet rs;

    public ResultSetWrapper(ResultSet rs) {
        this.rs = rs;
    }

    public ResultSet getResultSet() {
        return rs;
    }

    public Boolean getBoolean(String label) throws SQLException {
        final boolean b = rs.getBoolean(label);
        if (rs.wasNull()) {
            return null;
        }
        return b;
    }

    public Byte getByte(String label) throws SQLException {
        final byte b = rs.getByte(label);
        if (rs.wasNull()) {
            return null;
        }
        return b;
    }

    // ...

}

只是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;
}

在这个例子中,你的代码如下所示:

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

乐于得到反馈

您可以使用resultSet和具有Number类型的列名调用此方法。它将返回Integer值或null。数据库中的空值将不会返回零

private Integer getIntWithNullCheck(ResultSet rset, String columnName) {
    try {
        Integer value = rset.getInt(columnName);
        return rset.wasNull() ? null : value;
    } catch (Exception e) {
        return null;
    }
}

在Kotlin中,我只会解决它一次,并永远解决这个问题:

fun <K : Any> ResultSet.getNullable(columnLabel: String, type: KClass<K>): K? = 
    this.getObject(columnLabel, type.java)

之后你可以这样做:

rs.getNullable("ID_PARENT", Int::class)

我想如果你愿意,你也可以这样做

fun <K> ResultSet.getNullable(columnLabel: String, type: Class<K>): K? = 
    this.getObject(columnLabel, type)

所以你可以这样做:

rs.getNullable("ID_PARENT", Int::class.java)

如果你遇到的开发人员连最简单的事情都不能达成一致,最好还是同时提供两种方法。

fun <K : Any> ResultSet.getNullable(columnLabel: String, type: KClass<K>): K? =
        this.getNullable(columnLabel, type.java)

fun <K> ResultSet.getNullable(columnLabel: String, type: Class<K>): K? =
        this.getObject(columnLabel, type)

编辑:如果库仍然是挑剔的,你终于可以这样做:

rs.getNullable("ID_PARENT", String::class)?.let {FOO.valueOf(it) }