Você também pode usar um em ResultSetExtractor
vez 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 ResultSetExtractor
tem 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. JdbcTemplate
funciona 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 RowMapper
para 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 Account
objetos de domínio de uma consulta ( jt
é uma JdbcTemplate
instâ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 RowMapper
para 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 ResultSetExtractor
para a tarefa.
public static <T> ResultSetExtractor singletonExtractor(
RowMapper<? extends T> mapper) {
return rs -> rs.next() ? mapper.mapRow(rs, 1) : null;
}
Criar um ResultSetExtractor
agora 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.