Omet navegació

6.4 - Transaccions

Una transacció és un conjunt de sentències SQL d'actualització (INSERT, DELETE, UPDATE) que o bé s'executen totes o bé no s'executa ninguna.

La manera de confirmar les sentències és amb COMMIT, i la manera de rebutjar-les totes és ROLLBACK (quedant l'estat com estava abans de començar la transacció). En qualsevol dels dos casos, després d'executar les sedntències de control COMMIT o ROLLBACK, començarà una transacció nova.

JDBC trasllada també aquest metodologia al seu API. Per defecte, les connexions JDBC consideren que cada objecte Statement és en si mateix una transacció. Abans de cada execució es demana l’inici d’una transacció i al final, si l’execució té èxit, s’envia un commit i si no té èxit, un rollback. Per això diem que la connexió actua en mode autocommit.

Però hi ha una altra manera de funcionar. Els Statements poden treballar sense automatitzar el commit després de cada execució. Caldrà canviar la connexió de mode. Per canviar-la, executarem el mètode setAutoCommit(false).

A partir d’aleshores es consideraran instruccions d’una mateixa transacció totes les sentències executades entre dues cridades del mètode commit o rollback (equivalents JDBC de les instruccions COMMIT ROLLBACK de SQL).

A continuació mostrem una implementació genèrica que espera per paràmetre un array de sentències SQL que pertanyen a una mateixa transacció. La funció implementada executa sentència per sentència havent prèviament desactivat el mode autocommit. Si totes les sentències s’executen amb èxit es cridarà al mètode commit; en cas contrari es cridarà al mètode rollback. A la implementació hem suposat que la connexió ja existeix i es troba activa.

Aquest exemple seria part d'un programa més extens. No el podreu executar, només es mostra a nivell il·lustratiu.

public void executa(String[] sentenciesSql) throws SQLException{
boolean autocommit=true;
Statement stm = null;
try {
autocommit = con.getAutoCommit();
con.setAutoCommit(false);
stm = con.createStatement();
for(String sent: sentenciesSql){
stm.executeUpdate(sent);
}
con.commit();
con.setAutoCommit(autocommit);
} catch (SQLException ex) {
con.rollback();
throw ex;
}finally{
try {
if(stm!=null && !stm.isClosed()){
stm.close();
}
} catch (SQLException ex) {
Logger.getLogger(ProvesBasiques.class.getName()).log(Level.SEVERE, null, ex);
}
}
}

En tractar-se d’una connexió ja existent que s’utilitza en diversos mètodes, desactivarem sempre el mode autocommit a l’inici, però guardant-nos l'estat previ en la variable autocommit. Al final restituirem aquest valor guardat.

La major part de SGBD permeten utilitzar transaccions explícites amb qualsevol instrucció SQL, fins i tot en sentències DDL (data definition language) com CREATE TABLE, etc . Les sentències de definició modifiquen directament l’estructura de les dades i, per tant, cal anar molt en compte perquè poden provocar danys importants, pèrdues de dades existents, etc.

Però hi ha alguns SGBD com Oracle que no suporten la revocació de sentències DDL i en cas d’executar rollback, obtindrem un error indicant que les sentències DDL no es poden revocar. Per preveure casos com aquest caldrà capturar l’error i avisar l’usuari que no s’ha pogut restaurar la base de dades i que caldria revisar-la manualment.