transaction statement prepared parameter executeupdate example begin java database jdbc atomic

java - statement - Actualice más de una fila de forma atómica



resultset java example (3)

Usa transacciones

Necesito ejecutar una selección y luego actualizar algunas de las filas en el ResultSet de forma atómica.

El código que estoy usando parece (simplificado):

stmt = con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); rs = stmt.executeQuery("SELECT ..."); while (rs.next()) { if (conditions_to_update) { rs.updateString(...); rs.updateRow(); } }

  • ¿Puedo garantizar que las actualizaciones se ejecutarán atómicamente? Si no, ¿cómo podría asegurar eso?
  • ¿Qué sucede si cualquier otro proceso ha cambiado la fila de la base de datos que está actualizando a través de updateRow() ? ¿Hay alguna forma de bloquear las filas en el ResultSet ?

¿Qué sucede si cualquier otro proceso ha cambiado la fila de la base de datos que está actualizando a través de updateRow ()? ¿Hay alguna forma de bloquear las filas en el ResultSet?

En Oracle, puede marcar un poco ciertas filas para la actualización emitiendo el siguiente SQL.

select cola, colB from tabA for update;

La próxima transacción / hilo / aplicación que intente actualizar esta fila recibirá una excepción. mira esto para más detalles - http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:4530093713805


Es probable que haya un montón de tecnologías y conceptos que entran en juego aquí, y las cosas comienzan a ponerse bastante difíciles cuando comienzas a considerar las aplicaciones multi-threaded / multi request.

Como dijo Iassevk, debería considerar el uso de Transacciones para garantizar la naturaleza atómica de sus actualizaciones; un ejemplo de muy bajo nivel sería hacer algo como:

... con.setAutoCommit(false); try { while (rs.next()) { if (conditions_to_update) { rs.updateString(...); rs.updateRow(); } } con.setAutoCommit(true); } catch (Exception ex) { //log the exception and rollback con.rollback(); } finally { con.close(); }

Todas las actualizaciones se agruparán en la misma transacción. Si alguna de las actualizaciones generó una excepción (como un valor no válido o la conexión falla parcialmente en los resultados), todo el lote se retrotraería. (Finalmente agregado porque soy un campeón de él; p)

Sin embargo, esto no resolverá su segundo problema, que son dos métodos que compiten tratando de actualizar la misma tabla: una condición de carrera. Hay, en mi opinión, dos enfoques principales aquí: cada uno tiene sus ventajas y desventajas.

El enfoque más fácil sería bloquear la mesa , esto requeriría cambios mínimos de código, pero tiene un inconveniente bastante grande. Trabajando bajo la suposición de que, como la mayoría de las aplicaciones, es más leído que escribir: al bloquear la tabla se evitará que todos los demás usuarios vean los datos, con la probabilidad de que el código se cuelgue, esperando a que se libere antes de que finalice el tiempo de espera de la conexión. entra y lanza una excepción.

El enfoque más complejo es garantizar que los métodos para realizar estas actualizaciones se implementen de manera segura. Con ese fin:

  • Todas las actualizaciones de esta tabla pasan a través de una única clase
  • Esa clase implementa un patrón de Singleton o expone los métodos de actualización como métodos estáticos
  • Los métodos de actualización utilizan la palabra clave sincronizada para evitar condiciones de carrera