Możesz także użyć ResultSetExtractor
zamiast a RowMapper
. Oba są tak samo łatwe jak inne, jedyną różnicą jest to, że dzwonisz 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
Ma dodatkową zaletę, że można obsługiwać wszystkie przypadki, w których istnieje więcej niż jeden wiersz lub nie wierszy zwracanych.
AKTUALIZACJA : Kilka lat później mam kilka sztuczek, którymi mogę się podzielić. JdbcTemplate
działa znakomicie z lambdami java 8, dla których są przeznaczone poniższe przykłady, ale całkiem łatwo można użyć klasy statycznej, aby osiągnąć to samo.
Chociaż pytanie dotyczy typów prostych, te przykłady służą jako przewodnik w typowym przypadku wyodrębniania obiektów domeny.
Po pierwsze. Załóżmy, że dla uproszczenia masz obiekt konta z dwiema właściwościami Account(Long id, String name)
. Prawdopodobnie chciałbyś mieć RowMapper
dla tego obiektu domeny.
private static final RowMapper<Account> MAPPER_ACCOUNT =
(rs, i) -> new Account(rs.getLong("ID"),
rs.getString("NAME"));
Możesz teraz używać tego mapowania bezpośrednio w metodzie do mapowania Account
obiektów domeny z zapytania ( jt
jest to JdbcTemplate
instancja).
public List<Account> getAccounts() {
return jt.query(SELECT_ACCOUNT, MAPPER_ACCOUNT);
}
Świetnie, ale teraz chcemy uzyskać nasz pierwotny problem i używamy mojego oryginalnego rozwiązania, ponownie wykorzystując RowMapper
do wykonania mapowania za nas.
public Account getAccount(long id) {
return jt.query(
SELECT_ACCOUNT,
rs -> rs.next() ? MAPPER_ACCOUNT.mapRow(rs, 1) : null,
id);
}
Świetnie, ale jest to wzór, który możesz i zechcesz powtórzyć. Możesz więc utworzyć ogólną metodę fabryki, aby utworzyć nową ResultSetExtractor
dla zadania.
public static <T> ResultSetExtractor singletonExtractor(
RowMapper<? extends T> mapper) {
return rs -> rs.next() ? mapper.mapRow(rs, 1) : null;
}
Tworzenie ResultSetExtractor
teraz staje się trywialne.
private static final ResultSetExtractor<Account> EXTRACTOR_ACCOUNT =
singletonExtractor(MAPPER_ACCOUNT);
public Account getAccount(long id) {
return jt.query(SELECT_ACCOUNT, EXTRACTOR_ACCOUNT, id);
}
Mam nadzieję, że pomoże to pokazać, że można teraz dość łatwo łączyć części w potężny sposób, aby uprościć domenę.
AKTUALIZACJA 2 : Połącz z opcjonalnym dla wartości opcjonalnych zamiast null.
public static <T> ResultSetExtractor<Optional<T>> singletonOptionalExtractor(
RowMapper<? extends T> mapper) {
return rs -> rs.next() ? Optional.of(mapper.mapRow(rs, 1)) : Optional.empty();
}
Który teraz, gdy zostanie użyty, może mieć następujące cechy:
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()
byłby nazywany niepotrzebnie.ResultSetExtractor
W tym przypadku użycie a jest znacznie wydajniejszym narzędziem.