namedparameterjdbctemplate mkyong journaldev bean anotaciones java spring jdbc jdbctemplate

java - mkyong - JdbcTemplate queryForInt/Long está en desuso en Spring 3.2.2. ¿Por qué debería ser reemplazado?



spring jdbctemplate mkyong (6)

Los métodos queryforInt / queryforLong en JdbcTemplate están en desuso en Spring 3.2. No puedo averiguar por qué o qué se considera la mejor práctica para reemplazar el código existente utilizando estos métodos.

Un método típico:

int rowCount = jscoreJdbcTemplate.queryForInt( "SELECT count(*) FROM _player WHERE nameKey = ? AND teamClub = ?", playerNameKey.toUpperCase(), teamNameKey.toUpperCase() );

Aceptar el método anterior debe volver a escribirse de la siguiente manera:

Object[] params = new Object[] { playerNameKey.toUpperCase(), teamNameKey.toUpperCase() }; int rowCount = jscoreJdbcTemplate.queryForObject( "SELECT count(*) FROM _player WHERE nameKey = ? AND teamClub = ?", params, Integer.class);

Obviamente, esta degradación hace que la clase JdbcTemplate sea más simple (¿o no?). QueryForInt siempre fue un método de conveniencia (supongo) y ha existido por mucho tiempo. Por qué ha sido eliminado El código se vuelve más complicado como resultado.


Estoy de acuerdo con el póster original que desaprobar el método de conveniencia queryForLong (sql) es un inconveniente.

Desarrollé una aplicación usando Spring 3.1 y recién actualicé a la última versión de Spring (3.2.3) y noté que estaba en desuso.

Afortunadamente, fue un cambio de una línea para mí:

return jdbcTemplate.queryForLong(sql); // deprecated in Spring 3.2.x

fue cambiado a

return jdbcTemplate.queryForObject(sql, Long.class);

Y un par de pruebas unitarias parecen indicar que el cambio anterior funciona.


Lo que creo es que alguien se dio cuenta de que los métodos queryForInt / Long tienen una semántica confusa, es decir, desde el código fuente JdbcTemplate se puede ver su implementación actual:

@Deprecated public int queryForInt(String sql, Object... args) throws DataAccessException { Number number = queryForObject(sql, args, Integer.class); return (number != null ? number.intValue() : 0); }

lo que puede llevarlo a pensar que si el conjunto de resultados está vacío, devolverá 0, sin embargo arroja una excepción:

org.springframework.dao.EmptyResultDataAccessException: Incorrect result size: expected 1, actual 0

entonces la siguiente implementación es esencialmente equivalente a la actual:

@Deprecated public int queryForInt(String sql, Object... args) throws DataAccessException { return queryForObject(sql, args, Integer.class); }

Y luego el código no desaprobado ahora debe ser reemplazado por lo feo:

queryForObject(sql, new Object { arg1, arg2, ...}, Integer.class);

o esto (más agradable):

queryForObject(sql, Integer.class, arg1, arg2, ...);


Obsoleto a favor de queryForObject(String, Class) .


Reemplazar dicho código:

long num = jdbcTemplate.queryForLong(sql);

Con este código:

long num = jdbcTemplate.queryForObject(sql, Long.class);

es muy peligroso porque si la columna tiene valor nulo queryForObject devuelve nulo y, como sabemos, los tipos primitivos no pueden ser nulos y usted tendrá NullPointerException. El compilador no te advirtió acerca de esto. Conocerá este error en tiempo de ejecución. El mismo error que tendrá si tiene un método que devuelve tipo primitivo:

public long getValue(String sql) { return = jdbcTemplate.queryForObject(sql, Long.class); }

El método obsoleto queryForLong en JdbcTemplate en Spring 3.2.2 tiene el siguiente cuerpo:

@Deprecated public long queryForLong(String sql) throws DataAccessException { Number number = queryForObject(sql, Long.class); return (number != null ? number.longValue() : 0); }

Antes de que devuelvan el valor primitivo, verán que no es nulo y si es nulo, devuelven 0. Por cierto, debe ser 0L.


JdbcTemplate#queryForInt devuelve 0 si el valor de la columna es SQL NULL o 0. No hay forma de distinguir un caso del otro. Creo que esta es la razón principal por la cual el método está en desuso. Por cierto, ResultSet#getInt comporta de manera similar. Sin embargo, podemos distinguir entre estos dos casos por ResultSet#wasNull .


public int getCircleCount() { Object param = "1"; String sql = "select count(*) from circle where id = ? "; jdbcTemplate.setDataSource(getDataSource()); int result = getJdbcTemplate().queryForObject(sql, new Object[] { param }, Integer.class); return result; }