java - query - Usar declaraciones preparadas con JDBCTemplate
journaldev spring jdbctemplate (5)
Estoy usando la plantilla JDBC y quiero leer desde una base de datos usando declaraciones preparadas. Repito sobre muchas líneas en un archivo .csv, y en cada línea ejecuto algunas consultas de selección de SQL con los valores correspondientes.
Quiero acelerar mi lectura de la base de datos, pero no sé cómo hacer que la plantilla JDBC funcione con las declaraciones preparadas.
Está el PreparedStatementCreator y el PreparedStatementSetter . Como en este ejemplo, ambos se crean con clases internas anónimas. Pero dentro de la clase PreparedStatementSetter no tengo acceso a los valores que quiero establecer en la declaración preparada.
Como estoy iterando a través de un archivo .csv, no puedo codificarlos como una cadena porque no los conozco. Tampoco puedo pasarlos a PreparedStatementSetter porque no hay argumentos para el constructor. Y establecer mis valores al final sería tonto también.
Estaba acostumbrado a la creación de declaraciones preparadas siendo bastante simple. Algo como
PreparedStatement updateSales = con.prepareStatement(
"UPDATE COFFEES SET SALES = ? WHERE COF_NAME LIKE ? ");
updateSales.setInt(1, 75);
updateSales.setString(2, "Colombian");
updateSales.executeUpdate():
como en este tutorial de Java .
Consideraría el manejo de declaraciones preparado al menos a un método. En este caso, como no hay resultados, es bastante simple (y suponiendo que la conexión es una variable de instancia que no cambia):
private PreparedStatement updateSales;
public void updateSales(int sales, String cof_name) throws SQLException {
if (updateSales == null) {
updateSales = con.prepareStatement(
"UPDATE COFFEES SET SALES = ? WHERE COF_NAME LIKE ?");
}
updateSales.setInt(1, sales);
updateSales.setString(2, cof_name);
updateSales.executeUpdate();
}
En ese punto, solo es cuestión de llamar:
updateSales(75, "Colombian");
¿Qué es bastante simple de integrar con otras cosas, sí? Y si llama al método muchas veces, la actualización solo se construirá una vez y eso hará las cosas mucho más rápidas. Bueno, suponiendo que no hagas cosas locas como hacer cada actualización en su propia transacción ...
Tenga en cuenta que los tipos son fijos. Esto se debe a que para cualquier consulta / actualización en particular, deben corregirse para permitir que la base de datos haga su trabajo de manera eficiente. Si solo está tirando cadenas arbitrarias de un archivo CSV, páselos como cadenas. Tampoco hay bloqueo; mucho mejor para mantener las conexiones individuales para ser utilizado a partir de un solo hilo en su lugar.
De forma predeterminada, JDBCTemplate
realiza su propio PreparedStatement
internamente, si solo utiliza el .update(String sql, Object ... args)
. Spring y su base de datos administrarán la consulta compilada para usted, para que no tenga que preocuparse por abrir, cerrar, proteger recursos, etc. Una de las gracias de ahorro de Spring. Un enlace a la documentación de Spring 2.5 sobre esto. Espero que aclare las cosas. Además, el almacenamiento en caché de sentencias se puede realizar en el nivel JDBC, como en el caso de al menos algunos de los controladores JDBC de Oracle. Eso entrará en muchos más detalles de los que puedo competentemente.
Probé una declaración select ahora con un PreparedStatement
, pero resultó que no era más rápido que la plantilla Jdbc. Tal vez, como mezmo sugirió, crea automáticamente declaraciones preparadas.
De todos modos, la razón de que mi SQL SELECT
sea tan lenta fue otra. En la cláusula WHERE
siempre usé el operador LIKE
, cuando todo lo que quería hacer era encontrar una coincidencia exacta. Como he descubierto, LIKE
busca un patrón y, por lo tanto, es bastante lento.
Estoy usando el operador =
ahora y es mucho más rápido.
Pruebe lo siguiente:
PreparedStatementCreator creator = new PreparedStatementCreator() {
@Override
public PreparedStatement createPreparedStatement(Connection con) throws SQLException {
PreparedStatement updateSales = con.prepareStatement(
"UPDATE COFFEES SET SALES = ? WHERE COF_NAME LIKE ? ");
updateSales.setInt(1, 75);
updateSales.setString(2, "Colombian");
return updateSales;
}
};
class Main {
public static void main(String args[]) throws Exception {
ApplicationContext ac = new
ClassPathXmlApplicationContext("context.xml", Main.class);
DataSource dataSource = (DataSource) ac.getBean("dataSource");
// DataSource mysqlDataSource = (DataSource) ac.getBean("mysqlDataSource");
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
String prasobhName =
jdbcTemplate.query(
"select first_name from customer where last_name like ?",
new PreparedStatementSetter() {
public void setValues(PreparedStatement preparedStatement) throws
SQLException {
preparedStatement.setString(1, "nair%");
}
},
new ResultSetExtractor<Long>() {
public Long extractData(ResultSet resultSet) throws SQLException,
DataAccessException {
if (resultSet.next()) {
return resultSet.getLong(1);
}
return null;
}
}
);
System.out.println(machaceksName);
}
}