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