Jdbctemplate queryForInt / Long является устаревшим весной 3.2.2. Какой он должен быть заменен?


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

типичный прием:

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

ОК выше метод должен быть переписан следующим образом:

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 всегда был удобным методом (я думаю) и был вокруг долго. Почему он был удален. В результате код становится более сложным.

6 94

6 ответов:

Я думаю, что кто-то понял, что методы 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, ...);

Я согласен с оригинальным плакатом, что осуждение метода удобства 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);

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

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

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

long num = jdbcTemplate.queryForLong(sql);

этот код:

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

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

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

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

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

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

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

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