Sei que para desfazer transacoes em meu banco (access) posso utilizar o um rollback, , gostaria que caso alguem respondesse podesse colocar parte da sintaxe utilizada, espero resposta …
Na interface Connection tem o método rollback
public void rollback(Savepoint savepoint)
throws SQLExceptionUndoes all changes made after the given Savepoint object was set.
This method should be used only when auto-commit has been disabled.
Parameters:
savepoint - the Savepoint object to roll back to
Só que antes, você deve executar o setAutoCommit(false) (o default é true), senão toda declaração insert, update, etc vai ser comitada no banco de dados
Também tem o método rollback() (sem parâmetros)
Nem todo driver JDBC suporta SavePoints.
Mas vc só pode dar rollback quando vc tá sem AutoCommit. Um processo simples é o mostrado abaixo: primeiro, fazemos um update normal, usando uma query pré-definida, pra mostrar onde o driver faz o commit. Depois, tiramos o auto commit e fazemos isso “na mão”:
// código que insere no banco.
Connection conn = createConnection();
conn.setAutoCommit(true); // esse é o default pra quase 100% dos casos.
PreparedStatement stmt = conn.prepareStatement(queries.getProperty("usuarios.count.update"));
stmt.setInt(1, count);
stmt.executeUpdate(); // auto-committed
stmt.close();
conn.setAutoCommit(false); // queremos uma transação
try {
... // faz o que tem que fazer
conn.commit();
}
catch (SQLException e) {
conn.rollback();
}
finally {
conn.setAutoCommit(true); // voltamos ao estado original
}
Acho que deu pra sacar, né??
[]s
Valeu Galera, vc´s me ajudaram bastante, eu nao sabia que deveria colocar em meu catch, para desfazer …
Valeu, …
Ah, foi um exemplo!! Vc tem que dar rollback se deu algo errado na transação, neh??
Num contexto mais complexo, as condições para um rollback poderiam ser outras…
[]s
Realmente a J2SE obriga que a aplicação controle as transações.
Por isso sugiro que você tbm observe outros aspectos.
1- Chamar as transações de bancos de dados somente quando necessário, pois o uso indequado delas vai comprometer a performance.
2- Acessar o Banco de Dados usando um ConnectionPool, você pode fazer Download de um muito bom aqui:
http://cvs.apache.org/viewcvs/jakarta-commons/dbcp/
Ex:
import java.sql.*;
public class Database {
private String driver, url, user, password;
public Database(String driver, String url, String user, String pass) {
this.driver = driver;
this.url = url;
this.user = user;
this.pass = pass;
}
public void loadDriver() {
try {
Class.forName( driver );
} catch (Exception e) {
e.printStackTrace();
}
}
public Connection createConnection() throws SQLException {
// o ideal é que este metodo obtenha a conexão de um POOL.
Connection connection = null;
if ( user == null || pass == null ) {
connection = DriverManager.getConnection( url );
} else {
connection = DriverManager.getConnection( url, user, pass );
}
return connection;
}
public ArrayList select() throws SQLException {
Connection connection = createConnection();
connection.setAutoCommit(true);
connection.close();
}
public void insert() throws Exception {
Connection connection = null;
try {
connection = createConnection();
connection.setAutoCommit(false);
// insert data
connection.commit();
connection.close();
} catch (Exception e) {
connection.rollback();
connection.setAutoCommit(true);
throw new Exception( e.toString() );
}
}
public void update() throws Exception {
Connection connection = null;
try {
connection = createConnection();
connection.setAutoCommit(false);
// update data
connection.commit();
connection.close();
} catch (Exception e) {
connection.rollback();
connection.setAutoCommit(true);
throw new Exception( e.toString() );
}
}
public void delete() throws SQLException {
Connection connection = createConnection();
connection.setAutoCommit(true);
// delete data
connection.close();
}
}
Bom estudos.
Minha experiência também recomenda esconder o banco da aplicação, inclusive a parte de JDBC.
Eu sempre uso adapters para controlar o acesso ao banco, e muitas vezes tenho uma classe responsável por cuidar de uma parte do banco (um módulo, ou um tipo de acesso, ou mesmo um grupo de tabelas).
Mas quanto a connection pools, eu acho o dbcp do Jakarta impossível de usar. Primeiro pq não tem documentação suficiente, e depois porque vc acaba tendo que criar adapters muito complexos. Realmente, é uma API poderosíssima, mas eu não funciono muito bem sem Javadoc.
Eu até hoje prefiro fazer meu próprio pool com um LinkedList sincronizado. O problema é que vc tem que lembrar sempre de devolver a conexão pro banco, coisa que o dbcp faz sozinho. Mas como vc mesmo tá fazendo o adapter, não corre tanto risco.
E mesmo assim, eu sugiro que um método createConnection() sempre crie uma nova conexão. Ele não precisa ser público, é claro!! Mas use-o internamente para preencher seu pool e só. Pra pegar e devolver conexões, eu uso normalmente a dupla borrow/release:
/**
* cria uma nova conexão
**/
protected Connection createConnection(String connectUrl, String username, String password);
/**
* pega uma conexão do pool, bloqueando até haver alguma disponível. Equivale a borrowConnection(true);
**/
public Connection borrowConnection();
/**
* pega uma conexão do pool. Se block for true, bloqueia até ter uma conexão disponível, senão retorna null.
**/
public Connection borrowConnection(boolean block);
/**
* Devolve a conexão para o pool.
**/
public void releaseConnection(Connection c);
é bom pq vc pode criar conexões diferentes, ou pools de comportamento diferente, através de subclasses.
A utilização fica assim:
Connection c = adapter.borrowConnection();
c.setAutoCommit(false); // ah, vai ter transações!!
try {
... // faz o que tem que fazer
c.commit();
}
catch(PauFeioException e) {
c.rollback();
throw e;
}
finally {
adapter.releaseConnection(c);
}
[]s do duke!!