También puede utilizar a en ResultSetExtractor
lugar de a RowMapper
. Ambos son tan fáciles como el otro, la única diferencia es tu llamada 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;
}
});
}
El ResultSetExtractor
tiene la ventaja añadida de que puede manejar todos los casos en los que hay más de una fila o no hay filas devueltas.
ACTUALIZACIÓN : Varios años después y tengo algunos trucos para compartir. JdbcTemplate
funciona magníficamente con java 8 lambdas para las que están diseñados los siguientes ejemplos, pero puede usar fácilmente una clase estática para lograr lo mismo.
Si bien la pregunta es sobre tipos simples, estos ejemplos sirven como guía para el caso común de extracción de objetos de dominio.
Antes que nada. Supongamos que tiene un objeto de cuenta con dos propiedades para simplificar Account(Long id, String name)
. Es probable que desee tener un RowMapper
objeto para este dominio.
private static final RowMapper<Account> MAPPER_ACCOUNT =
(rs, i) -> new Account(rs.getLong("ID"),
rs.getString("NAME"));
Ahora puede usar este mapeador directamente dentro de un método para mapear Account
objetos de dominio desde una consulta ( jt
es una JdbcTemplate
instancia).
public List<Account> getAccounts() {
return jt.query(SELECT_ACCOUNT, MAPPER_ACCOUNT);
}
Genial, pero ahora queremos nuestro problema original y usamos mi solución original reutilizando el RowMapper
para realizar el mapeo por nosotros.
public Account getAccount(long id) {
return jt.query(
SELECT_ACCOUNT,
rs -> rs.next() ? MAPPER_ACCOUNT.mapRow(rs, 1) : null,
id);
}
Genial, pero este es un patrón que puede y querrá repetir. Por lo tanto, puede crear un método de fábrica genérico para crear uno nuevo ResultSetExtractor
para la tarea.
public static <T> ResultSetExtractor singletonExtractor(
RowMapper<? extends T> mapper) {
return rs -> rs.next() ? mapper.mapRow(rs, 1) : null;
}
Crear un ResultSetExtractor
ahora se vuelve trivial.
private static final ResultSetExtractor<Account> EXTRACTOR_ACCOUNT =
singletonExtractor(MAPPER_ACCOUNT);
public Account getAccount(long id) {
return jt.query(SELECT_ACCOUNT, EXTRACTOR_ACCOUNT, id);
}
Espero que esto ayude a demostrar que ahora puede combinar partes con bastante facilidad de una manera poderosa para simplificar su dominio.
ACTUALIZACIÓN 2 : Combine con un Opcional para valores opcionales en lugar de nulos.
public static <T> ResultSetExtractor<Optional<T>> singletonOptionalExtractor(
RowMapper<? extends T> mapper) {
return rs -> rs.next() ? Optional.of(mapper.mapRow(rs, 1)) : Optional.empty();
}
Que ahora cuando se usa podría tener lo siguiente:
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()
se llamaría innecesariamente. El uso de aResultSetExtractor
es una herramienta mucho más eficiente en este caso.