En capítulos anteriores hemos podido obtener un conjunto de resultados a partir de una consulta. Además hemos visto como nos podemos desplazar por el conjunto de resultados. A continuación veremos como se pueden modificar los datos del conjunto y volcar las modificaciones en la base de datos.
Lo primero es comprobar si nuestro gestor de base de datos nos permite modificar conjuntos de resultados. Existen unas constantes static en la clase ResultSet que identifican el ResulSet en función de si pueden o no actualizar la base de datos:
| CONCUR_READ_ONLY | El ResultSet no puede modificar la base de datos. |
| CONCUR_UPDATABLE | El ResultSet puede modificar la base de datos. |
Una vez que hayamos establacido la conexión, tenemos que obtener un objeto de la clase Statement que admita actualizaciones de ResultSet. Para ello tenemos una versión de createStatement que dispará una excepción del tipo SQLException, en el caso de que la base de datos no permita el tipo señalado en resultSetType o resultSetConcurrency:
public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException
Como ejemplo:
String orden_SQL = "SELECT codigo, nombre FROM cliente ORDER BY nombre"; Statement sentencia = con.createStatement( ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = sentencia.executeQuery( orden_SQL );
Lo anterior es una forma sencilla y adecuada de tener un ResultSet actualizable. Veamos a continuación una forma erronea de crear un ResultSet actualizable. Si el objeto de tipo Statement se ha obtenido con la llamada a createStatement sin argumentos:
Statement sentencia = con.createStatement( );Nos puede ocurrir que al modificar el ResultSet:
/*** Nos ponemos en el primero y lo modificamos ***/ rs.first(); rs.updateString( "nombre", "Joaquín"); rs.updateRow();Se dispare una excepción. ¿Por qué? Estamos modificando un conjunto de resultados, pero el Statement del que proviene no admite esta capacidad:
com.mysql.jdbc.NotUpdatable: Result Set not updatable.This result set must come from a statement that was created with a result set type of ResultSet.CONCUR_UPDATABLE
También podemos saber si el conjunto permite actualización mediante un método de ResulSet:
public int getConcurrency()
Que devuelve la capacidad del ResultSet en la forma de las constantes antes descritas. Otro método para averiguar la capacidad de un ResultSet implica el manejo de metadatos, que ya hemos visto en otros capítulos:
boolean DatabaseMetaData.supportsResultSetConcurrency(int type, int concurrency) throws SQLException
Dispará una excepción del tipo SQLException, en el caso de que la base de datos no permita el tipo señalado en resultSetType o resultSetConcurrency.
Hay que tener en cuenta que no todas las consultas que nos devuelven un conjunto
de resultados nos permiten actualización (aunque el gestor de base de datos si
lo permita). La razón de esto puede ser que la consulta implique a varias tablas
y que no estén enlazadas por el enlace de clave primaria - clave externa o que
incluyendo varias tablas la consulta no incluya las claves primarias.
Actualizar
Unas sencillas líneas de ejemplo:
/***** Definir sentencia y ejecutarla ********/ String orden_SQL = "SELECT codigo, nombre FROM cliente ORDER BY nombre"; Statement sentencia = con.createStatement( ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs = sentencia.executeQuery( orden_SQL ); /*** Nos ponemos en el primero y lo modificamos ***/ rs.first(); rs.updateString( "nombre", "Joaquín"); rs.updateRow();
Lo primero es obtener un objeto Statement por medio de crateStatement; este objeto permite scroll (desplazamiento) y actualización . A continuación nos situamos mediante first() en la fila que queremos modificar (la primera) y realizamos el cambio de la columna "nombre" con updateString(), indicando en su segundo argumento el nuevo valor ("Joaquín"). Hay una versión de updateXXX() para cada tipo de campo: String, Double, etc.
Es importante destacar que la modificación se refiere al ResultSet, concretamente
a la fila actual del ResultSet, y si nos movemos a otra fila los cambios se perderán,
a menos que antes del desplazamiento llames a updateRow(). Unicamente updateRow() vuelca los cambios a la base de datos. Con el método cancelRowUpdates() cancelamos las modificaciones DE LA FILA ACTUAL.
Inserción y borrado
Después de haber aprendido la actualización, la inserción no resulta difícil. Lo primero es desplazar el cursor a una posición especial, una pseudofila en blanco, mediante una llamada a moveToInsertRow() de la clase ResultSet. A continuación usamos updateXXX( String nombre_columna, nuevo_valor ) para dar valores a las columnas:
rs.moveToInsertRow();
rs.updateString( "codigo", "OJD33");
rs.updateString(
"nombre", "Pedro Juan");
rs.updateInt( "edad", 34 );
rs.insertRow();
// Guardar en base de datos
rs.moveToCurrentRow(); // Volvemos
a la posición anterior a hacer moveToInsertRow
Con moveToCurrentRow() movemos el cursor a la posición anterior a la llamada a moveToInsertRow. En nuestro ejemplo la posición que ocupa el registro insertado depende de la cláusula ORDER BY de la consulta.
El borrado es extremadamente sencillo: el método deleteRow() borra la fila activa tanto del ResultSet como de la base de datos.
Sensatez
El manejo de ResultSet con actualización es una herramienta sencilla y muy utilizada. Pero conviene hacer alguna consideración: