Ви також можете використовувати 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
тепер стає банальним.
private static final ResultSetExtractor<Account> EXTRACTOR_ACCOUNT =
singletonExtractor(MAPPER_ACCOUNT);
public Account getAccount(long id) {
return jt.query(SELECT_ACCOUNT, EXTRACTOR_ACCOUNT, id);
}
Я сподіваюся, що це допоможе показати, що тепер ви можете досить легко комбінувати деталі потужним чином, щоб зробити свій домен простішим.
ОНОВЛЕННЯ 2 : комбінуйте з необов'язковими для необов'язкових значень замість null.
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
є набагато ефективнішим інструментом у цьому випадку.