Você também pode usar um em ResultSetExtractorvez de a RowMapper. Ambos são tão fáceis um quanto o outro, a única diferença é você ligar 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;
}
});
}
O ResultSetExtractortem a vantagem adicional de poder lidar com todos os casos em que há mais de uma linha ou nenhuma linha retornada.
ATUALIZAÇÃO : Vários anos depois, tenho alguns truques para compartilhar. JdbcTemplatefunciona muito bem com java 8 lambdas, para os quais os exemplos a seguir foram projetados, mas você pode facilmente usar uma classe estática para fazer o mesmo.
Embora a questão seja sobre tipos simples, esses exemplos servem como um guia para o caso comum de extração de objetos de domínio.
Primeiramente. Vamos supor que você tenha um objeto de conta com duas propriedades para simplificar Account(Long id, String name). Você provavelmente gostaria de ter um RowMapperpara este objeto de domínio.
private static final RowMapper<Account> MAPPER_ACCOUNT =
(rs, i) -> new Account(rs.getLong("ID"),
rs.getString("NAME"));
Agora você pode usar este mapeador diretamente em um método para mapear Accountobjetos de domínio de uma consulta ( jté uma JdbcTemplateinstância).
public List<Account> getAccounts() {
return jt.query(SELECT_ACCOUNT, MAPPER_ACCOUNT);
}
Ótimo, mas agora queremos nosso problema original e usamos minha solução original reutilizando o RowMapperpara realizar o mapeamento para nós.
public Account getAccount(long id) {
return jt.query(
SELECT_ACCOUNT,
rs -> rs.next() ? MAPPER_ACCOUNT.mapRow(rs, 1) : null,
id);
}
Ótimo, mas esse é um padrão que você pode e deseja repetir. Portanto, você pode criar um método de fábrica genérico para criar um novo ResultSetExtractorpara a tarefa.
public static <T> ResultSetExtractor singletonExtractor(
RowMapper<? extends T> mapper) {
return rs -> rs.next() ? mapper.mapRow(rs, 1) : null;
}
Criar um ResultSetExtractoragora se torna 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 isso ajude a mostrar que agora você pode combinar facilmente partes de uma maneira poderosa para tornar seu domínio mais simples.
ATUALIZAÇÃO 2 : Combine com um Opcional para valores opcionais em vez de nulo.
public static <T> ResultSetExtractor<Optional<T>> singletonOptionalExtractor(
RowMapper<? extends T> mapper) {
return rs -> rs.next() ? Optional.of(mapper.mapRow(rs, 1)) : Optional.empty();
}
Que agora, quando usado, poderia ter o seguinte:
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()seria chamado desnecessariamente. Usar aResultSetExtractoré uma ferramenta muito mais eficiente neste caso.