Puoi anche usare un ResultSetExtractorinvece 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' ResultSetExtractorha 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. JdbcTemplatefunziona 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 RowMapperper 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 Accountoggetti del dominio da una query ( jtè JdbcTemplateun'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 RowMapperper 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 ResultSetExtractorper l'attività.
public static <T> ResultSetExtractor singletonExtractor(
RowMapper<? extends T> mapper) {
return rs -> rs.next() ? mapper.mapRow(rs, 1) : null;
}
Creare un ResultSetExtractoradesso 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.