Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I'm trying to see if there is a better way to do this when I just need one column with one row. Do not mind the lack of use of a prepared statement, I will put it in.

public <T> T getValueFromDb(String col, String table, String cond, Class<T> returnValueClass) {

    T val = null;

    try {
        ResultSet rs = getSet("SELECT " + col + " FROM " + table + " WHERE " + cond);
        if(rs.next()) {
            if(returnValueClass == Integer.class) {
                val = (T) (Integer) rs.getInt(col);
            } else if(returnValueClass == Double.class) {
                val = (T) (Double) rs.getDouble(col);
            } else if(returnValueClass == String.class) {
                val = (T) rs.getString(col);
            }
        }
        closeSetQuietly(rs);
    } catch(SQLException sql) {
        Log.logException(null, sql);
    }

    return val;

}

Should I just perhaps do just:

returnValueClass.cast(rs.getInt(x));
share|improve this question
    
What should one do when a null is returned from this method? Does not a value meeting the passed in condition exist? Or did an exception occurred while trying to read from the DB? Or did the passed in class is not one of the few supported ones? – abuzittin gillifirca Jul 17 '13 at 9:04
up vote 4 down vote accepted

Using polymorphism is the way to get an great solution. You are receiving the class in your method just to infer the the return type while you could abstract the idea of conversion and use it to do the inference too. Let's create an interface to convert the result and its implementations:

interface ResultTransformer<T> {
    T transform(ResultSet rs, String column) throws SQLException;
}

public class IntegerResultTransformer implements ResultTransformer<Integer> {
    public Integer transform(ResultSet rs, String column) throws SQLException {
        return rs.getInt(column);
    }
}

public class StringResultTransformer implements ResultTransformer<String> {
    public String transform(ResultSet rs, String column) throws SQLException {
        return rs.getString(column);
    }
}

public class DoubleResultTransformer implements ResultTransformer<Double> {
    public Double transform(ResultSet rs, String column) throws SQLException {
        return rs.getDouble(column);
    }
}

Now the method will receive a ResultTransformer and just call its method transform:

public <T> T getValueFromDb2(String col, String table, String cond, ResultTransformer<T> transformer) {
    // concatenate strings isn't a good idea, 
    // use the PreparedStatement methods: setString, setDouble and so on
    ResultSet rs = getSet("SELECT " + col + " FROM " + table + " WHERE " + cond);
    try {
        return transformer.transform(rs, col);
    } catch (SQLException e) {
        throw new RuntimeException(e); // don't return null
    }
}

Using the method:

Integer anInteger = getValueFromDb2("col", "table", "cond", new IntegerResultTransformer());
String aString = .getValueFromDb2("col", "table", "cond", new StringResultTransformer());
Double aDouble = .getValueFromDb2("col", "table", "cond", new DoubleResultTransformer());

For now on, you just need to create a new ResultTransform implementation.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.