Estoy usando Jdbctemplate para recuperar un solo valor de cadena de la base de datos. Este es mi 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;
}
En mi escenario, es completamente posible NO obtener un resultado en mi consulta, por lo que mi pregunta es cómo puedo solucionar el siguiente mensaje de error.
EmptyResultDataAccessException: Incorrect result size: expected 1, actual 0
Me parece que debería obtener un valor nulo en lugar de lanzar una excepción. ¿Cómo puedo arreglar esto? Gracias por adelantado.
fuente
ResultSet.next()
se llamaría innecesariamente. El uso de aResultSetExtractor
es una herramienta mucho más eficiente en este caso.return null
encatch(EmptyResultDataAccessException exception){ return null; }
?También puede utilizar a en
ResultSetExtractor
lugar de aRowMapper
. Ambos son tan fáciles como el otro, la única diferencia es tu llamadaResultSet.next()
.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 unRowMapper
objeto para este dominio.Ahora puede usar este mapeador directamente dentro de un método para mapear
Account
objetos de dominio desde una consulta (jt
es unaJdbcTemplate
instancia).Genial, pero ahora queremos nuestro problema original y usamos mi solución original reutilizando el
RowMapper
para realizar el mapeo por nosotros.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.Crear un
ResultSetExtractor
ahora se vuelve trivial.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.
Que ahora cuando se usa podría tener lo siguiente:
fuente
Esa no es una buena solución porque depende de las excepciones para controlar el flujo. En su solución, es normal obtener excepciones, es normal tenerlas en el registro.
fuente
ResultSet.next()
se llamaría innecesariamente. El uso de aResultSetExtractor
es una herramienta mucho más eficiente en este caso.De hecho, puedes jugar
JdbcTemplate
y personalizar tu propio método como prefieras. Mi sugerencia es hacer algo como esto:Funciona como el original
jdbc.queryForObject
, pero sinthrow new EmptyResultDataAccessException
cuándosize == 0
.fuente
UserMapper implements RowMapper<String>
.DataAccessUtils.singleResult(...)
es lo que estaba buscando. ThxDado que devolver un valor nulo cuando no hay datos es algo que quiero hacer a menudo cuando uso queryForObject, me ha resultado útil extender JdbcTemplate y agregar un método queryForNullableObject similar al siguiente.
Ahora puede usar esto en su código de la misma manera que usó queryForObject
Me interesaría saber si alguien más piensa que esta es una buena idea.
fuente
Ok, lo descubrí. Simplemente lo envolví en un intento de captura y devolví nulo.
fuente
Con Java 8 o superior, puede utilizar un
Optional
y Java Streams.Entonces, simplemente puede usar el
JdbcTemplate.queryForList()
método, crear un Stream y usar elStream.findFirst()
que devolverá el primer valor del Stream o un vacíoOptional
:Para mejorar el rendimiento de la consulta, puede agregar
LIMIT 1
a su consulta, de modo que no se transfiera más de 1 elemento de la base de datos.fuente
Puede utilizar una función de grupo para que su consulta siempre devuelva un resultado. es decir
fuente
En Postgres, puede hacer que casi cualquier consulta de valor único devuelva un valor o nulo envolviéndola:
y por lo tanto evitar la complejidad en la persona que llama.
fuente
Desde getJdbcTemplate (). QueryForMap espera un tamaño mínimo de uno, pero cuando devuelve un valor nulo, muestra EmptyResultDataAccesso fix dis cuando se puede usar a continuación la lógica
fuente
Me ocupé de esto antes y había publicado en los foros de primavera.
http://forum.spring.io/forum/spring-projects/data/123129-frustrated-with-emptyresultdataaccessexception
El consejo que recibimos fue utilizar un tipo de SQlQuery. A continuación, se muestra un ejemplo de lo que hicimos al intentar obtener un valor de una base de datos que podría no estar allí.
En el DAO, simplemente llamamos ...
No está claro en cuanto al rendimiento, pero funciona y está limpio.
fuente
Para Byron, puedes probar esto ...
fuente
para hacer
funciona, asegúrese de que su jdbcTemplate sea de tipo
fuente
Podemos usar query en lugar de queryForObject, la principal diferencia entre query y queryForObject es que la lista de retorno de la consulta de Object (basada en el tipo de retorno del asignador de filas) y esa lista puede estar vacía si no se reciben datos de la base de datos, mientras que queryForObject siempre espera que solo un solo objeto sea obtenido de db ni filas nulas ni múltiples y, en caso de que el resultado esté vacío, queryForObject arroja EmptyResultDataAccessException, había escrito un código usando una consulta que superará el problema de EmptyResultDataAccessException en caso de resultado nulo.
fuente
En mi humilde opinión, devolver un
null
es una mala solución porque ahora tiene el problema de enviarlo e interpretarlo en el (probable) cliente de interfaz. Tuve el mismo error y lo resolví simplemente devolviendo un archivoList<FooObject>
. Yo uséJDBCTemplate.query()
.En el front-end (cliente web angular), simplemente examino la lista y si está vacía (de longitud cero), la trato como si no se encontraran registros.
fuente
Acabo de captar esta "EmptyResultDataAccessException"
entonces puedes comprobar:
fuente