Puoi anche usare un ResultSetExtractor
invece di un RowMapper
. Entrambi sono altrettanto facili l'uno dell'altro, l'unica differenza è che chiami 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;
}
});
}
L' ResultSetExtractor
ha il vantaggio che è possibile gestire tutti i casi in cui ci sono più di una riga o nessun righe restituite.
AGGIORNAMENTO : Sono passati diversi anni e ho alcuni trucchi da condividere. JdbcTemplate
funziona in modo eccellente con java 8 lambda per i quali sono progettati i seguenti esempi, ma puoi facilmente usare una classe statica per ottenere lo stesso risultato.
Sebbene la domanda riguardi i tipi semplici, questi esempi servono come guida per il caso comune di estrazione di oggetti di dominio.
Prima di tutto. Supponiamo di avere un oggetto account con due proprietà per semplicità Account(Long id, String name)
. Probabilmente vorresti avere un RowMapper
per questo oggetto di dominio.
private static final RowMapper<Account> MAPPER_ACCOUNT =
(rs, i) -> new Account(rs.getLong("ID"),
rs.getString("NAME"));
È ora possibile utilizzare questo mappatore direttamente all'interno di un metodo per mappare gli Account
oggetti del dominio da una query ( jt
è JdbcTemplate
un'istanza).
public List<Account> getAccounts() {
return jt.query(SELECT_ACCOUNT, MAPPER_ACCOUNT);
}
Ottimo, ma ora vogliamo il nostro problema originale e usiamo la mia soluzione originale riutilizzando il RowMapper
per eseguire la mappatura per noi.
public Account getAccount(long id) {
return jt.query(
SELECT_ACCOUNT,
rs -> rs.next() ? MAPPER_ACCOUNT.mapRow(rs, 1) : null,
id);
}
Ottimo, ma questo è uno schema che potresti e vorresti ripetere. Quindi puoi creare un metodo factory generico per crearne uno nuovo ResultSetExtractor
per l'attività.
public static <T> ResultSetExtractor singletonExtractor(
RowMapper<? extends T> mapper) {
return rs -> rs.next() ? mapper.mapRow(rs, 1) : null;
}
Creare un ResultSetExtractor
adesso diventa banale.
private static final ResultSetExtractor<Account> EXTRACTOR_ACCOUNT =
singletonExtractor(MAPPER_ACCOUNT);
public Account getAccount(long id) {
return jt.query(SELECT_ACCOUNT, EXTRACTOR_ACCOUNT, id);
}
Spero che questo aiuti a dimostrare che ora puoi combinare abbastanza facilmente le parti in un modo potente per rendere il tuo dominio più semplice.
AGGIORNAMENTO 2 : Combina con un facoltativo per i valori facoltativi invece di null.
public static <T> ResultSetExtractor<Optional<T>> singletonOptionalExtractor(
RowMapper<? extends T> mapper) {
return rs -> rs.next() ? Optional.of(mapper.mapRow(rs, 1)) : Optional.empty();
}
Che ora, se utilizzato, potrebbe avere quanto segue:
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()
verrebbe chiamato inutilmente. L'utilizzo di aResultSetExtractor
è uno strumento molto più efficiente in questo caso.