Estou usando o Jdbctemplate para recuperar um único valor String do banco de dados. Aqui está meu método.
public String test() {
String cert=null;
String sql = "select ID_NMB_SRZ from codb_owner.TR_LTM_SLS_RTN
where id_str_rt = '999' and ID_NMB_SRZ = '60230009999999'";
cert = (String) jdbc.queryForObject(sql, String.class);
return cert;
}
No meu cenário, é totalmente possível NÃO obter uma resposta em minha consulta, então minha pergunta é como faço para contornar a seguinte mensagem de erro.
EmptyResultDataAccessException: Incorrect result size: expected 1, actual 0
Parece-me que devo apenas obter um valor nulo em vez de lançar uma exceção. Como posso consertar isso? Desde já, obrigado.
fonte
ResultSet.next()
seria chamado desnecessariamente. Usar aResultSetExtractor
é uma ferramenta muito mais eficiente neste caso.return null
emcatch(EmptyResultDataAccessException exception){ return null; }
?Você também pode usar um em
ResultSetExtractor
vez de aRowMapper
. Ambos são tão fáceis um quanto o outro, a única diferença é você ligarResultSet.next()
.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 umRowMapper
para este objeto de domínio.Agora você pode usar este mapeador diretamente em um método para mapear
Account
objetos de domínio de uma consulta (jt
é umaJdbcTemplate
instância).Ótimo, mas agora queremos nosso problema original e usamos minha solução original reutilizando o
RowMapper
para realizar o mapeamento para nós.Ó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.Criar um
ResultSetExtractor
agora se torna trivial.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.
Que agora, quando usado, poderia ter o seguinte:
fonte
Essa não é uma boa solução porque você está contando com exceções para o fluxo de controle. Na sua solução é normal obter exceções, é normal tê-las no log.
fonte
ResultSet.next()
seria chamado desnecessariamente. Usar aResultSetExtractor
é uma ferramenta muito mais eficiente neste caso.Ok, eu descobri. Acabei de envolvê-lo em um try catch e enviar de volta null.
fonte
Na verdade, você pode brincar
JdbcTemplate
e personalizar seu próprio método como preferir. Minha sugestão é fazer algo assim:Funciona como o original
jdbc.queryForObject
, mas semthrow new EmptyResultDataAccessException
quandosize == 0
.fonte
UserMapper implements RowMapper<String>
.DataAccessUtils.singleResult(...)
é o que eu estava procurando. ThxComo retornar um valor nulo quando não há dados é algo que eu quero fazer com frequência ao usar queryForObject, achei útil estender JdbcTemplate e adicionar um método queryForNullableObject semelhante ao abaixo.
Agora você pode usar isso em seu código da mesma maneira que usou queryForObject
Gostaria de saber se mais alguém acha que isso é uma boa ideia.
fonte
Usando Java 8 ou superior, você pode usar um
Optional
e Java Streams.Então você pode simplesmente usar o
JdbcTemplate.queryForList()
método, criar um Stream e usar oStream.findFirst()
que retornará o primeiro valor do Stream ou um vazioOptional
:Para melhorar o desempenho da consulta, você pode anexar
LIMIT 1
à sua consulta, de forma que não mais de 1 item seja transferido do banco de dados.fonte
Você pode usar uma função de grupo para que sua consulta sempre retorne um resultado. ie
fonte
No Postgres, você pode fazer com que quase qualquer consulta de valor único retorne um valor ou nulo envolvendo-o:
e, portanto, evita a complexidade do chamador.
fonte
Já que getJdbcTemplate (). QueryForMap espera tamanho mínimo de um, mas quando retorna null mostra EmptyResultDataAccesso corrige dis quando pode usar a lógica abaixo
fonte
Eu lidei com isso antes e havia postado nos fóruns da primavera.
http://forum.spring.io/forum/spring-projects/data/123129-frustrated-with-emptyresultdataaccessexception
O conselho que recebemos foi usar um tipo de SQlQuery. Aqui está um exemplo do que fizemos ao tentar obter um valor de um banco de dados que pode não estar lá.
No DAO então apenas ligamos ...
Não está claro no desempenho, mas funciona e é legal.
fonte
Para Byron, você pode tentar isso ..
fonte
fazer
trabalho, certifique-se de que seu jdbcTemplate é do tipo
fonte
Podemos usar query em vez de queryForObject, a principal diferença entre query e queryForObject é que a lista de retorno da consulta do Object (com base no tipo de retorno do Row mapper) e essa lista pode estar vazia se nenhum dado for recebido do banco de dados, enquanto queryForObject sempre espera que apenas um único objeto seja buscado do banco de dados nem nulo nem linhas múltiplas e, caso o resultado seja vazio, queryForObject lança EmptyResultDataAccessException. Eu escrevi um código usando consulta que superará o problema de EmptyResultDataAccessException em caso de resultado nulo.
fonte
IMHO retornar um
null
é uma solução ruim porque agora você tem o problema de enviar e interpretar no (provável) cliente front-end. Eu tive o mesmo erro e resolvi simplesmente retornando aList<FooObject>
. eu useiJDBCTemplate.query()
.No front end (cliente Web Angular), eu simplesmente examino a lista e, se ela estiver vazia (de comprimento zero), a considero como nenhum registro encontrado.
fonte
Acabei de pegar esta "EmptyResultDataAccessException"
então você pode verificar:
fonte