Checking for a null int value from a Java ResultSet

JavaNullResultset

Java Problem Overview


In Java I'm trying to test for a null value, from a ResultSet, where the column is being cast to a primitive int type.

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

From the code fragment above, is there a better way to do this, and I assume that the second wasNull() test is redundant?

Educate us, and Thanks

Java Solutions


Solution 1 - Java

The default for ResultSet.getInt when the field value is NULL is to return 0, which is also the default value for your iVal declaration. In which case your test is completely redundant.

If you actually want to do something different if the field value is NULL, I suggest:

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

(Edited as @martin comments below; the OP code as written would not compile because iVal is not initialised)

Solution 2 - Java

Another solution:

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

Solution 3 - Java

I think, it is redundant. rs.getObject("ID_PARENT") should return an Integer object or null, if the column value actually was NULL. So it should even be possible to do something like:

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

Solution 4 - Java

Just check if the field is null or not using ResultSet#getObject(). Substitute -1 with whatever null-case value you want.

int foo = resultSet.getObject("foo") != null ? resultSet.getInt("foo") : -1;

Or, if you can guarantee that you use the right DB column type so that ResultSet#getObject() really returns an Integer (and thus not Long, Short or Byte), then you can also just typecast it to an Integer.

Integer foo = (Integer) resultSet.getObject("foo");

Solution 5 - Java

AFAIK you can simply use

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

even if it is NULL.

Solution 6 - Java

Just an update with Java Generics.

You could create an utility method to retrieve an optional value of any Java type from a given ResultSet, previously casted.

Unfortunately, getObject(columnName, Class) does not return null, but the default value for given Java type, so 2 calls are required

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

In this example, your code could look like below:

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

Happy to get feedback

Solution 7 - Java

You can call this method using the resultSet and the column name having Number type. It will either return the Integer value, or null. There will be no zeros returned for empty value in the database

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

Solution 8 - Java

With java 8 you can do this:

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

In that case you ensure that the nVal will be null (and not zero) if the SQL value is NULL

Solution 9 - Java

For convenience, you can create a wrapper class around ResultSet that returns null values when ResultSet ordinarily would not.

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;
	}
	
	// ...
	
}

Solution 10 - Java

Just in case someone comes here while programming in Kotlin (as I did), the answer suggested by BalusC works fine. Just be aware that Short and Float are instantiated as Integer and Double (respectively) inside ResultSet, and we should cast them to the correct type after calling getObject(). In my case the final code was:

when {
    propKClass.isSubclassOf(Int::class) -> rs.getObject(colName) as Int? 
    propKClass.isSubclassOf(Short::class) -> (rs.getObject(colName) as Int?)?.toShort()
    propKClass.isSubclassOf(Long::class) -> rs.getObject(colName) as Long?
    propKClass.isSubclassOf(Boolean::class) -> rs.getObject(colName) as Boolean?
    propKClass.isSubclassOf(Double::class) -> rs.getObject(colName) as Double?
    propKClass.isSubclassOf(Float::class) -> (rs.getObject(colName) as Double?)?.toFloat()
    else -> rs.getString(colName)
}

Solution 11 - Java

If you want an alternative to calling ResultSet.wasNull() you can use getObject() and cast to the correct type.

Long val = (Long)rs.getObject(pos++);

You can also set null values in a Statement with setObject().

pstmt.setObject(pos++, null);

Solution 12 - Java

Another nice way of checking, if you have control the SQL, is to add a default value in the query itself for your int column. Then just check for that value.

e.g for an Oracle database, use NVL

SELECT NVL(ID_PARENT, -999) FROM TABLE_NAME;

then check

if (rs.getInt('ID_PARENT') != -999)
{
}

Of course this also is under the assumption that there is a value that wouldn't normally be found in the column.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionian_schoView Question on Stackoverflow
Solution 1 - JavaRichardView Answer on Stackoverflow
Solution 2 - JavaPatrice IMBERTView Answer on Stackoverflow
Solution 3 - JavaAndreas DolkView Answer on Stackoverflow
Solution 4 - JavaBalusCView Answer on Stackoverflow
Solution 5 - JavaPeter TillemansView Answer on Stackoverflow
Solution 6 - JavaluchoctView Answer on Stackoverflow
Solution 7 - Javaamine kriaaView Answer on Stackoverflow
Solution 8 - JavaGeorgeView Answer on Stackoverflow
Solution 9 - JavaJacob CroftsView Answer on Stackoverflow
Solution 10 - JavaGilson AraujoView Answer on Stackoverflow
Solution 11 - JavaChad JulianoView Answer on Stackoverflow
Solution 12 - JavaChrisView Answer on Stackoverflow