JdbcTemplate queryForInt/Long устарел в Spring 3.2.2. Что его нужно заменить?

Методы queryforInt/queryforLong в JdbcTemplate устарели в Spring 3.2. Я не могу понять, почему или что считается лучшей практикой для замены существующего кода с помощью этих методов.

Типичный метод:

int rowCount = jscoreJdbcTemplate.queryForInt(
    "SELECT count(*) FROM _player WHERE nameKey = ? AND teamClub = ?",
    playerNameKey.toUpperCase(),
    teamNameKey.toUpperCase()
);

OK вышеуказанный метод необходимо переписать следующим образом:

Object[] params = new Object[] { 
   playerNameKey.toUpperCase(), 
   teamNameKey.toUpperCase()
};
int rowCount = jscoreJdbcTemplate.queryForObject(
    "SELECT count(*) FROM _player WHERE nameKey = ? AND teamClub = ?",
    params, Integer.class);

Очевидно, что эта усталость делает класс JdbcTemplate более простым (или делает это?). QueryForInt всегда был методом удобства (я думаю) и был вокруг долгого времени. Почему он был удален. В результате код становится более сложным.

Ответ 1

Я думаю, что кто-то понял, что методы queryForInt/Long запутывают семантику, то есть из исходного кода JdbcTemplate вы можете увидеть ее текущую реализацию:

@Deprecated
public int queryForInt(String sql, Object... args) throws DataAccessException {
    Number number = queryForObject(sql, args, Integer.class);
    return (number != null ? number.intValue() : 0);
}

который может заставить вас думать, что если набор результатов пуст, он вернет 0, однако он выдает исключение:

org.springframework.dao.EmptyResultDataAccessException: Incorrect result size: expected 1, actual 0

поэтому следующая реализация по существу эквивалентна текущей:

@Deprecated
public int queryForInt(String sql, Object... args) throws DataAccessException {
    return queryForObject(sql, args, Integer.class);
}

И тогда не устаревший код теперь должен быть заменен на уродливый:

    queryForObject(sql, new Object { arg1, arg2, ...}, Integer.class);

или это (лучше):

    queryForObject(sql, Integer.class, arg1, arg2, ...);

Ответ 2

Я согласен с оригинальным плакатом, что неудобство метода удобства queryForLong (sql) является неудобством.

Я разработал приложение, использующее Spring 3.1 и обновленное до последней версии Spring (3.2.3), и заметил, что он устарел.

К счастью, для меня это было однострочное изменение:

return jdbcTemplate.queryForLong(sql);  // deprecated in Spring 3.2.x

был изменен на

return jdbcTemplate.queryForObject(sql, Long.class);

И, по-видимому, несколько тестов Unit показывают, что приведенное выше изменение работает.

Ответ 3

Усталость в пользу queryForObject(String, Class).

Ответ 4

Замена такого кода:

long num = jdbcTemplate.queryForLong(sql);

С помощью этого кода:

long num = jdbcTemplate.queryForObject(sql, Long.class);

очень опасен, потому что, если столбец имеет нулевое значение, запросForObject возвращает null, и, как мы знаем, примитивные типы не могут быть нулевыми, и у вас будет исключение NullPointerException. Компилятор не предупредил вас об этом. Об этой ошибке вы узнаете во время выполнения. Та же ошибка, которую вы получите, если у вас есть метод, возвращающий примитивный тип:

public long getValue(String sql) {
    return = jdbcTemplate.queryForObject(sql, Long.class);
}

Устаревший метод queryForLong в JdbcTemplate в Spring 3.2.2 имеет следующий элемент:

@Deprecated
public long queryForLong(String sql) throws DataAccessException {
    Number number = queryForObject(sql, Long.class);
    return (number != null ? number.longValue() : 0);
}

Вы увидите, прежде чем они вернут примитивное значение, проверьте, что это не пустое и если оно равно null, они возвращают 0. Кстати, должно быть 0L.

Ответ 5

JdbcTemplate#queryForInt возвращает 0, если значение столбца равно SQL NULL или 0. Невозможно отличить один случай от другого. Я думаю, что это основная причина, почему метод устарел. BTW, ResultSet#getInt ведет себя аналогичным образом. Хотя мы можем различать эти два случая на ResultSet#wasNull.

Ответ 6

public int getCircleCount() {
    Object param = "1";
    String sql = "select count(*) from circle where id = ? ";
    jdbcTemplate.setDataSource(getDataSource());
    int result = getJdbcTemplate().queryForObject(sql, new Object[] { param }, Integer.class);
    return result;
}