studio programacion para móviles libro edición desarrollo desarrollar curso aprende aplicaciones java jdbc prepared-statement

java - programacion - Reutilizar una declaración preparada varias veces



manual de programacion android pdf (2)

en el caso de utilizar PreparedStatement con una única conexión común sin ningún grupo, ¿puedo volver a crear una instancia para cada operación dml / sql manteniendo el poder de las declaraciones preparadas?

Quiero decir:

for (int i=0; i<1000; i++) { PreparedStatement preparedStatement = connection.prepareStatement(sql); preparedStatement.setObject(1, someValue); preparedStatement.executeQuery(); preparedStatement.close(); }

en lugar de:

PreparedStatement preparedStatement = connection.prepareStatement(sql); for (int i=0; i<1000; i++) { preparedStatement.clearParameters(); preparedStatement.setObject(1, someValue); preparedStatement.executeQuery(); } preparedStatement.close();

mi pregunta surge por el hecho de que quiero poner este código en un entorno multiproceso, ¿me pueden dar algún consejo? Gracias


El ciclo de tu código es solo un ejemplo demasiado simplificado, ¿verdad?

Sería mejor crear PreparedStatement solo una vez, y volver a usarlo una y otra vez en el ciclo.

En situaciones en las que eso no es posible (porque complica demasiado el flujo del programa), sigue siendo beneficioso usar un Estado Preparado, incluso si lo usa solo una vez, porque el lado del servidor del trabajo (analizando el SQL y almacenando en caché el plan de ejecución), aún se reducirá.

Para abordar la situación en la que desea volver a utilizar el PreparedStatement del lado de Java, algunos controladores JDBC (como Oracle) tienen una característica de almacenamiento en caché: si crea un PreparedStatement para el mismo SQL en la misma conexión, le dará el mismo instancia (en caché).

Acerca de multi-threading: no creo que las conexiones JDBC puedan compartirse entre varios hilos (es decir, usadas al mismo tiempo por varios hilos) de todos modos. Cada hilo debe obtener su propia conexión del grupo, usarla y devolverla al grupo nuevamente.


La segunda forma es un poco más eficiente, pero una forma mucho mejor es ejecutarlos en lotes:

public void executeBatch(List<Entity> entities) throws SQLException { try ( Connection connection = dataSource.getConnection(); PreparedStatement statement = connection.prepareStatement(SQL); ) { for (Entity entity : entities) { statement.setObject(1, entity.getSomeProperty()); // ... statement.addBatch(); } statement.executeBatch(); } }

Sin embargo, depende de la implementación del controlador JDBC cuántos lotes podría ejecutar a la vez. Por ejemplo, puede querer ejecutarlos cada 1000 lotes:

public void executeBatch(List<Entity> entities) throws SQLException { try ( Connection connection = dataSource.getConnection(); PreparedStatement statement = connection.prepareStatement(SQL); ) { int i = 0; for (Entity entity : entities) { statement.setObject(1, entity.getSomeProperty()); // ... statement.addBatch(); i++; if (i % 1000 == 0 || i == entities.size()) { statement.executeBatch(); // Execute every 1000 items. } } } }

En cuanto a los entornos multiproceso, no necesita preocuparse por esto si adquiere y cierra la conexión y la declaración en el ámbito más corto posible dentro del mismo bloque de método según la expresión JDBC normal utilizando la declaración try-with-resources como se muestra en fragmentos de arriba

Si esos lotes son transaccionales, entonces desea desactivar la confirmación automática de la conexión y solo comprometer la transacción cuando finalicen todos los lotes. De lo contrario, puede dar lugar a una base de datos sucia cuando el primer grupo de lotes tuvo éxito y el otro no.

public void executeBatch(List<Entity> entities) throws SQLException { try (Connection connection = dataSource.getConnection()) { connection.setAutoCommit(false); try (PreparedStatement statement = connection.prepareStatement(SQL)) { // ... try { connection.commit(); } catch (SQLException e) { connection.rollback(); throw e; } } } }