Вы также можете использовать ResultSetExtractor
вместо RowMapper
. Оба так же просты, как и друг друга, разница только в том, что вы звоните ResultSet.next()
.
public String test() {
String sql = "select ID_NMB_SRZ from codb_owner.TR_LTM_SLS_RTN "
+ " where id_str_rt = '999' and ID_NMB_SRZ = '60230009999999'";
return jdbc.query(sql, new ResultSetExtractor<String>() {
@Override
public String extractData(ResultSet rs) throws SQLException,
DataAccessException {
return rs.next() ? rs.getString("ID_NMB_SRZ") : null;
}
});
}
ResultSetExtractor
Имеет дополнительное преимущество , что вы можете обрабатывать все случаи , когда Есть более чем одна строка или нет строк , возвращаемых.
ОБНОВЛЕНИЕ : прошло несколько лет, и у меня есть несколько уловок. JdbcTemplate
великолепно работает с лямбдами java 8, для которых предназначены следующие примеры, но вы можете легко использовать статический класс для достижения того же.
Хотя речь идет о простых типах, эти примеры служат руководством для общего случая извлечения объектов предметной области.
Прежде всего. Предположим, что у вас есть объект учетной записи с двумя свойствами для простоты Account(Long id, String name)
. Вероятно, вы захотите иметь RowMapper
для этого объекта домена.
private static final RowMapper<Account> MAPPER_ACCOUNT =
(rs, i) -> new Account(rs.getLong("ID"),
rs.getString("NAME"));
Теперь вы можете использовать это средство сопоставления непосредственно в методе для сопоставления Account
объектов домена из запроса ( jt
является JdbcTemplate
экземпляром).
public List<Account> getAccounts() {
return jt.query(SELECT_ACCOUNT, MAPPER_ACCOUNT);
}
Отлично, но теперь нам нужна наша исходная проблема, и мы используем мое исходное решение, повторно используя RowMapper
для выполнения сопоставления для нас.
public Account getAccount(long id) {
return jt.query(
SELECT_ACCOUNT,
rs -> rs.next() ? MAPPER_ACCOUNT.mapRow(rs, 1) : null,
id);
}
Отлично, но это шаблон, который вы можете и захотите повторить. Таким образом, вы можете создать общий фабричный метод для создания новой ResultSetExtractor
задачи.
public static <T> ResultSetExtractor singletonExtractor(
RowMapper<? extends T> mapper) {
return rs -> rs.next() ? mapper.mapRow(rs, 1) : null;
}
Создание ResultSetExtractor
now становится тривиальным.
private static final ResultSetExtractor<Account> EXTRACTOR_ACCOUNT =
singletonExtractor(MAPPER_ACCOUNT);
public Account getAccount(long id) {
return jt.query(SELECT_ACCOUNT, EXTRACTOR_ACCOUNT, id);
}
Я надеюсь, что это поможет показать, что теперь вы можете довольно легко комбинировать части мощным способом, чтобы упростить свой домен.
ОБНОВЛЕНИЕ 2 : объедините с необязательным для необязательных значений вместо нуля.
public static <T> ResultSetExtractor<Optional<T>> singletonOptionalExtractor(
RowMapper<? extends T> mapper) {
return rs -> rs.next() ? Optional.of(mapper.mapRow(rs, 1)) : Optional.empty();
}
Который теперь при использовании может иметь следующее:
private static final ResultSetExtractor<Optional<Double>> EXTRACTOR_DISCOUNT =
singletonOptionalExtractor(MAPPER_DISCOUNT);
public double getDiscount(long accountId) {
return jt.query(SELECT_DISCOUNT, EXTRACTOR_DISCOUNT, accountId)
.orElse(0.0);
}
ResultSet.next()
было бы вызвано без необходимости. В этом случае использование aResultSetExtractor
- гораздо более эффективный инструмент.