Bloqueo optimista en aplicaciones JDBC
Puede escribir aplicaciones JDBC para sacar provecho del bloqueo optimista sobre una fuente de datos.
El bloqueo optimista es una técnica que las aplicaciones pueden utilizar para liberar bloqueos entre operaciones SELECT y UPDATE o DELETE. Si las filas seleccionadas cambian antes de que la aplicación realice la actualización o supresión, la operación UPDATE o DELETE falla. El bloqueo optimista minimiza el tiempo durante el cual un recurso determinado no puede ser utilizado por otras transacciones.
Para conexiones con una fuente de datos Db2 para IBM® i, la utilización del bloqueo optimista requiere Db2 para IBM i V6R1 o posterior.
En general, una aplicación sigue estos pasos para utilizar el bloqueo optimista:
- Selecciona filas de una tabla.
- Libera bloqueos mantenidos en la tabla.
- Actualiza las filas seleccionadas, si no han cambiado.
Para comprobar si la fila ha cambiado, la aplicación consulta el símbolo de cambio de fila. El símbolo de cambio de fila no es siempre un indicador exacto de si una fila ha cambiado. Si crea una tabla con una columna de indicación de fecha y hora de cambio de fila, el símbolo de cambio de fila es totalmente exacto. Si crea la tabla sin una columna de indicación de fecha y hora de cambio de fila, o modifica una tabla para añadir una columna de indicación de fecha y hora de cambio de fila, el símbolo de cambio de fila puede que no refleje fielmente las actualizaciones hechas en una fila. Esto significa que el símbolo de cambio de fila puede indicar que una fila ha cambiado aunque no sea así. Esta condición se denomina condición de negativo falso.
Cuando escriba una aplicación JDBC para realizar un bloqueo optimista, seguirá pasos similares:
- Prepare y ejecute una consulta.
Indique si desea información sobre el bloqueo optimista y si esa información puede incluir negativos falsos.
- Determine si el ResultSet tiene información
sobre el bloqueo optimista y si esa información puede producir
negativos falsos.
Basándose en el tipo de información sobre el bloqueo optimista, puede decidir si desea continuar utilizando el bloqueo optimista.
- Libera bloqueos mantenidos en la tabla.
- Actualice las filas seleccionadas, si el símbolo de cambio de fila indica que las filas no han cambiado.
El código siguiente muestra cómo una aplicación JDBC puede realizar el bloqueo optimista. Los números contenidos en el ejemplo corresponden a los pasos listados anteriormente.
com.ibm.db2.jcc.DB2Statement s1 =
(com.ibm.db2.jcc.DB2Statement)conn.createStatement();
ResultSet rs =
((com.ibm.db2.jcc.DB2Statement)s1).executeDB2OptimisticLockingQuery
("SELECT EMPNO, SALARY FROM EMP WHERE EMP.LASTNAME = 'HAAS'",
com.ibm.db2.jcc.DB2Statement.RETURN_OPTLOCK_COLUMN_NO_FALSE_NEGATIVES); 1
// Indica que desea realizar bloqueo
// optimista, y que desea información
// sobre bloqueo optimista que
// no produzca negativos falsos
ResultSetMetaData rsmd = rs.getMetaData();
int optColumns = 2
((com.ibm.db2.jcc.DB2ResultSetMetaData)rsmd).getDB2OptimisticLockingColumns();
// Recupere la información sobre
// el bloqueo optimista.
boolean optColumnsReturned = false;
if (optColumns == 0); // Si no se devuelve información sobre
// bloqueo optimista, no intente realizar
// bloqueo optimista.
else if (optColumns == 1); // El valor 1 no se devuelve nunca si se especifica
// RETURN_OPTLOCK_COLUMN_NO_FALSE_NEGATIVES,
// pues 1 indica que podría haber negativos
// falsos.
else if (optColumns == 2) // Si se devuelve información sobre bloqueo
optColumnsReturned = true; // optimista y no aparecerán negativos falsos,
// intente utilizar el bloqueo optimista.
rs.next(); // Recupere el contenido de ResultSet
int emp_id = rs.getInt(1);
double salary = rs.getDouble(2);
long rowChangeToken = 0;
Object rid = null;
int type = -1;
if (optColumnsReturned) {
rowChangeToken = // Obtenga el símbolo de cambio de fila.
((com.ibm.db2.jcc.DB2ResultSet)rs).getDB2RowChangeToken();
rid = ((com.ibm.db2.jcc.DB2ResultSet)rs).getDB2RID();
// Obtenga RID, que sirve para
// identificar la fila de forma exclusiva.
int type = ((com.ibm.db2.jcc.DB2ResultSet)rs).getDB2RIDType ();
// Obtenga el tipo de datos del RID.
}
// ***************************************************
// Libere los bloqueos o desconecte de la base de datos.
// Realice algunas tareas sobre los datos recuperados.
// Vuelva a conectar con la fuente de datos.
// ***************************************************
…
PreparedStatement s2 =
conn.prepareStatement ("UPDATE EMP SET SALARY = ? " +
"WHERE EMPNO = ? AND ROW CHANGE TOKEN FOR EMP = ? and " +
"RID_BIT(EMP) = ?");
// Sentencia para actualizar las
// filas seleccionadas previamente
// que no han cambiado.
s2.setDouble(1, salary+10000);
s2.setInt(2, emp_id);
// Establezca los nuevos valores de la fila.
s2.setLong(3, rowChangeToken);
// Establezca el símbolo de cambio de fila
// de la fila recuperada anteriormente.
if (type == java.sql.Types.BIGINT)
s2.setLong (4, ((Long)rid).longValue());
else if (type == java.sql.Types.VARBINARY)
s2.setBytes (4, (byte[])rid);
// Establezca el RID de la fila
// recuperada anteriormente.
// Utilice el método setXXX correcto
// para el tipo de datos del RID.
int updateCount = s2.executeUpdate(); 3
// Realice la actualización.
if (updateCount == 1); // La actualización ha sido satisfactoria.
else // La actualización ha fallado.
…